在C# 应用程序开发, 我们经常要UI作线程分开,防止界面停止响应。  同一时候我们又须要在工作线程中更新UI界面上的控件,

以下介绍几种经常使用的方法

阅读文件夹

  1. 线程间操作无效
  2. 第一种办法:禁止编译器对跨线程訪问做检查
  3. 另外一种办法: 使用delegate和invoke来从其它线程中调用控件
  4. 第三种办法: 使用delegate和BeginInvoke来从其它线程中控制控件
  5. 第四种办法: 使用BackgroundWorker组件
  6. 源码下载

线程间操作无效

界面上有一个button和一个label,  点击button会启动一个线程来更新Label的值

        private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel));
thread1.Start("更新Label");
} private void UpdateLabel(object str)
{
this.label1.Text = str.ToString();
}

执行后。 程序会报错 "跨线程操作无效,从不是创建"label1"的线程訪问它"

这是由于.NET禁止了跨线程调用控件。 否则谁都能够操作控件,最后可能造成错误。

以下介绍几种跨线程调用控件的方法

第一种办法:禁止编译器对跨线程訪问做检查

这是最简单的办法, 相当于不检查线程之间的冲突。同意各个线程随便乱搞,最后Lable1控件的值是什么就难以预料了 (不推荐使用这样的方法)

        public Form1()
{
InitializeComponent();
// 增加这行
Control.CheckForIllegalCrossThreadCalls = false;
}

另外一种办法: 使用delegate和invoke来从其它线程中调用控件

调用控件的invoke方法。就能够控制控件了,比如

        private void button2_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel2));
thread1.Start("更新Label");
} private void UpdateLabel2(object str)
{
if (label2.InvokeRequired)
{
// 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想訪问它
Action<string> actionDelegate = (x) => { this.label2.Text = x.ToString(); };
// 或者
// Action<string> actionDelegate = delegate(string txt) { this.label2.Text = txt; };
this.label2.Invoke(actionDelegate, str);
}
else
{
this.label2.Text = str.ToString();
}
}

第三种办法: 使用delegate和BeginInvoke来从其它线程中控制控件

仅仅要把上面的 this.label2.Invoke(actionDelegate, str); 中的 Invoke 改为BeginInvoke方法就能够了

Invoke方法和BeginInvoke方法的差别是

Invoke方法是同步的, 它会等待工作线程完毕。

BeginInvoke方法是异步的, 它会另起一个线程去完毕工作线程

第四种办法: 使用BackgroundWorker组件(推荐使用这种方法)

BackgroundWorker是.NET里面用来运行多线程任务的控件。它同意编程者在一个单独的线程上运行一些操作。耗时的操作(例如以下载和数据库事务)。

使用方法简单

        private void button4_Click(object sender, EventArgs e)
{
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync("Tank");
}
} void bw_DoWork(object sender, DoWorkEventArgs e)
{
// 这里是后台线程, 是在还有一个线程上完毕的
// 这里是真正做事的工作线程
// 能够在这里做一些费时的。复杂的操作
Thread.Sleep(5000);
e.Result = e.Argument + "工作线程完毕";
} void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//这时后台线程已经完毕。并返回了主线程。所以能够直接使用UI控件了
this.label4.Text = e.Result.ToString();
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

C# 跨线程呼叫控制的更多相关文章

  1. [WinForm]WinForm跨线程UI操作常用控件类大全

    前言 在C#开发的WinForm窗体程序开发的时候,经常会使用多线程处理一些比较耗时之类的操作.不过会有一个问题:就是涉及到跨线程操作UI元素. 相信才开始接触的人一定会遇上这个问题. 为了解决这个问 ...

  2. c#中多线程同步Lock(锁)的研究以及跨线程UI的操作

    本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象.由于想更直观的显示结果,所以,在做demo的时候,就把多线程通过事件操作UI的代码也写了出来,留作备忘和分享吧. 其实多线程的同步,使用 ...

  3. winform 跨线程操作控件

    当进行winform的开发时,经常遇到用时比较久的操作,在传统的单线程程序中,用户必须等待这个耗时操作完成以后才能进行下一步的操作,这个时候,多线程编程就派上用场了,将这个耗时的操作放到一个新的子线程 ...

  4. 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件 corss thread operation”异常

    在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件.但对于数据绑定bindingList而言,没法响应 ...

  5. c#跨线程访问控件帮助类

    1.背景 对于winform程序来说,当我们点击按钮,需要消耗一定时长才能拿到数据后才能显示在界面上某个控件上的情况,我们通常会专门开一个线程去拿数据,这样不会造成界面处于假死状态 2.常规做法 // ...

  6. WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)

    最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...

  7. C#跨线程操作控件

    1.首先通过按键创建子线程: 创建子线程,子线程调用changeText方法. private void btnOK_Click(object sender, EventArgs e) { Threa ...

  8. 简短总结一下C#里跨线程更新UI(转)

    摘自: http://my.oschina.net/sdqxcxh/blog/53707 跨线程更新UI是写多线程程序尤其是通信类的程序经常遇到的问题,这里面主要的问题是冲突,比如数据线程想要更新UI ...

  9. C# 跨线程调用控件

    在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应.  同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线程间操作无效 第一种办法:禁 ...

随机推荐

  1. 猫学习IOS(五岁以下儿童)UI之360其他下载管理器广场UI

    猫分享.必须精品 下载材料:http://blog.csdn.net/u013357243/article/details/44486651 先看效果 主要是完毕了九宫格UI的搭建 代码 - (voi ...

  2. BackGroundWorker使用总结

    方法: backgroundWorker1.CancelAsync() 用于取消异步执行 backgroundWorker1.ReportProgress(int ,object)用于向主线层报告进度 ...

  3. 【转】C# string和StringBuilder的区别

    主要的区别在于 stringbuilder相对于string,效率要高些,string会在每次改变的时候进行内存重新组合,而stringbuilder则不会从新组合,另外stringbuilder有a ...

  4. 几款开源ESB总线的比较(转)

    现有的开源ESB总线中,自从2003年第一个开源总线Mule出现后,现在已经是百花争鸣的景象了.现在我就对现有的各种开源ESB总线依据性能.可扩展性.资料文档完整程度以及整合难易程度等方面展开. CX ...

  5. 【原版的】Redis事件驱动内核

    Redis事件驱动内核 作者:cf (360电商技术组) 概述 Redis实现了自己的事件驱动,与开源事件库libevent.libev一样,都是基于I/O多路复用技术实现的.出于性能和代码精炼双方面 ...

  6. Gray Code -- LeetCode

    原标题链接: http://oj.leetcode.com/problems/gray-code/  这道题要求求出n位的格雷码相应的二进制数,主要在于找到一种格雷码的递增方法(格雷码并非唯一的,能够 ...

  7. IE8/IE9无法启用JavaScript怎么办

    在IE8/IE9 中,有些同学在浏览网页时,收到提示:“需要启用 JavaScript …”,并且会发现网页上某些功能不能用了,比如点击网页里的按钮没反应等等.这个是因为浏览器的JavaScript ...

  8. Java多线程&lt;1&gt;

    1.Java多线程的概念: 线(Thread):它指的是一个任务的从开始执行流程到结束. 穿线提供执行任务的机构.供java条款.在一个程序可以启动多个并发线程.候执行. 在单处理器系统中,多个线程共 ...

  9. 使用js在新窗口中POST数据

    最近在做自己的博客,写文章的时候有一个预览功能,当时使用的是弹出框来进行预览,感觉体验不是很好. 然后想到了写邮件时候的新窗口预览,查了下126邮箱和qq邮箱的预览实现效果,以及各种谷歌百度stack ...

  10. c# 16进制显示转化

    非原创. 接收16进制数据,在TextBox委托显示: private void readPortandShow() { char[] HexChar = { '0', '1', '2', '3', ...