在.NET中,如果我们在非UI线程上访问窗体上的控件的时候,会产生一个跨线程调用的异常,那么如何处理这种情况呢?在上一章中,我介绍了使用Control.Invoke方法,如果你不习惯使用委托,那么.Net还为我们提供了一个组件BackgroundWorker,你可以使用这个组件,以事件的方式去处理这种跨线程的控件访问。下面我就来详细的介绍一下这个组件的用法。

我们先来看一下BackgroundWorker提供了哪些常用的成员,

事件

◆DoWork:我们在这个事件中,执行需要异步处理的工作。

◆ProgressChanged:我们在这个事件中,接收并处理异步处理过程中的信息。

◆RunWorkerCompleted:我们在这个事件中,执行异步处理结束的工作。

方法

◆RunWorkerAsync()和RunWorkerAsync(object argument):这两个方法触发DoWork事件,开始异步操作。

◆ReportProgress(int percentProgress)和ReportProgress(int percentProgress, object userState):这两个方法触发ProgressChanged事件。

◆CancelAsync:结束后台的异步操作。

属性

◆bool CancellationPending:指示当前的后台的异步操作是否正在被取消,执行CancelAsync方法会导致这个属性为true。

◆bool IsBusy:指示当前的后台异步操作是否正在进行,进行中为true。

◆bool WorkerReportsProgress:获取或设置当前的BackgroundWorker是否可以执行ProgressChanged方法。

◆bool WorkerSupportsCancellation:获取或设置当前的BackgroundWorker是否可以执行CancelAsync方法。

OK,有了上面这些成员,我们来看一下BackgroundWorker是如何工作的。

Step 1. 当然是定义一个BackgroundWorker的实例,你可以从工具箱中拖拽一个BackgroundWorker控件到窗体上或者在代码中直接声明;

Step 2. 生成DoWork事件并在DoWork事件的中添加需要异步执行的代码。在异步执行的代码中,如果需要处理界面中的控件,请调用ReportProgress方法,而不要直接处理(例如给控件赋值),因为DoWork事件跟正常的界面的事件不同,这个事件在非UI线程上执行,所以才能异步执行。

Step 3. 生成ProgressChanged事件并添加控件处理的代码,因为这个事件是在UI线程上执行的,所以可以给界面中的控件进行赋值等操作。

Step 4. 如果需要,请生成RunWorkerCompleted事件,在此处理异步执行结束的业务逻辑。当然,此事件也是在UI线程上执行的,可以给界面中的控件进行赋值等操作。

Step 5. 在需要执行异步操作的地方调用RunWorkerAsync方法,开始执行异步调用。

下面是具体的代码:

        public Form1()     {     InitializeComponent();    bWorker.DoWork += new DoWorkEventHandler(bWorker_DoWork);    bWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bWorker_RunWorkerCompleted);   bWorker.ProgressChanged += new ProgressChangedEventHandler(bWorker_ProgressChanged);     this.Text = "UI thread id is:" + Thread.CurrentThread.ManagedThreadId.ToString();     }     BackgroundWorker bWorker = new BackgroundWorker();void bWorker_DoWork(object sender, DoWorkEventArgs e){int tick = (int)e.Argument;Thread thr = Thread.CurrentThread;for (int i = 0; i < 30; i++){if (bWorker.CancellationPending){e.Cancel = true;//break;    }else{Thread.Sleep(TimeSpan.FromSeconds(tick));bWorker.ReportProgress(i, DateTime.Now.ToString() + "\\TID:" + thr.ManagedThreadId.ToString());}}}void bWorker_ProgressChanged(object sender, ProgressChangedEventArgs e){progressBar1.Value = e.ProgressPercentage;label1.Text = e.UserState.ToString();}void bWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){label1.Text = DateTime.Now.ToString();progressBar1.Value = progressBar1.Maximum;if (e.Cancelled)label1.Text = "User cancelled.";}private void btnInvoke_Click(object sender, EventArgs e){bWorker.WorkerReportsProgress = true;bWorker.WorkerSupportsCancellation = true;if (!bWorker.IsBusy)bWorker.RunWorkerAsync(1);}private void btnCancel_Click(object sender, EventArgs e){if (bWorker.WorkerSupportsCancellation)bWorker.CancelAsync();}

上面的代码请注意几个地方:

1. 第45行,开始调用RunWorkerAsync方法前,请先判断IsBusy属性是否是false,因为如果为true,则说明上一次的调用还没有结束,再次调用会引发异常。

2. 第50行,调用CancelAsync方法前,请先设置WorkerSupportsCancellation属性为true,否则会引发异常。

3. 第43行,调用ReportProgress方法前,请先设置WorkerReportsProgress属性为true,否则会引发异常。

4. RunWorkerAsync方法传递的参数是object类型,这个参数的值可以在DoWork事件的参数e中的属性Argument获得。

5. ReportProgress方法传递的参数可以在事件ProgressChanged中的参数e中获得。

6. 调用CancelAsync方法只是向后台的异步线程发出结束申请,具体什么时候结束,由线程自动管理。

7. 在RunWorkerCompleted事件中,如果想知道后台任务是正常执行完毕还是被调用CancelAsync方法强制中断,请参考事件的参数e的Cancelled属性。(奇怪的是这个属性不会在你调用CancelAsync方法后自动设置为true,你需要象代码中的20行那样进行设置。)

8. 请注意第7行和第26行的代码,这两段代码中的线程的ID,说明了DoWork事件和UI是在两个不同的线程上执行。

实际上BackgroundWorker并非直接用来解决跨线程的控件调用的问题,只是它提供了一种工作机制,可以让你的程序利用它来执行异步调用,并且在异步调用的过程中进行控件的操作。

好了,关于如何对界面中的控件进行跨线程的调用就介绍这么多吧,希望对大家有所帮助。

本文链接:http://www.cnblogs.com/atree/archive/2010/08/03/BackgroundWorker-DoWork.html

原文标题: 在.Net中进行跨线程的控件操作

链接:http://www.cnblogs.com/happinessCodes/archive/2010/07/22/1783199.html

C#.NET跨线程控件的相关操作相关推荐

  1. 三种跨线程控件访问方法

    1.不安全的方法: 将 Control.CheckForIllegalCrossThreadCalls 设置为false (.net1.0中没有) 2.安全的方法: 异步委托(不要将除了控件访问外其他 ...

  2. 关于跨线程操作GUI线程控件的疑问

    单元测试能够帮助开发人员确保所开发的模块.类以及类中的方法等的正确性,在项目开发过程中,及时进行单元测试能够避免不必要的BUG以及提高测试效率. 在本文中,我们会分别来学习如何使用MSTest.xUn ...

  3. python--文件的相关操作

    1.文件的基本操作 文件打开的格式: file = open(文件路径,读写模式) 文件路径:可以写相对路径,也可以写绝对路径 读写模式:r(读取) w(写入) a(追加) 文件打开后,必须关闭,否则 ...

  4. 【WPF】使用Tab键Focus控件的相关操作

    页面 一个页面(窗口)中默认的使用Tab键时,默认Focus元素的顺序是按xmal页面的控件的顺序 在代码中如果想调整某些控件的顺序,可以在代码中使用KeyboardNavigation.SetTab ...

  5. Python GUI库TKinter子线程与主线程控件传递消息策略

    TKinter GUI库没有像MFC那样的强制安全策略,在MFC中子线程无法直接控制主线程中的GUI控件,比如修改文本框或者按钮上的内容.因为如果只有2个线程,即一个主线程和一个子线程的情况下子线程直 ...

  6. CORS跨域实现思路及相关解决方案

    CORS跨域实现思路及相关解决方案 参考文章: (1)CORS跨域实现思路及相关解决方案 (2)https://www.cnblogs.com/safoie/p/10547788.html 备忘一下.

  7. Xamarin XAML语言教程控件模板的模板绑定

    Xamarin XAML语言教程控件模板的模板绑定 控件模板的模板绑定 为了可以轻松更改控件模板中控件上的属性值,可以在控件模板中实现模板绑定功能.模板绑定允许控件模板中的控件将数据绑定到公共属性上. ...

  8. 全网最详细SpringBatch读(Reader)跨多行文件讲解

    文章列表 读记录跨多行文件 1.读跨多行文件job配置 2.读跨多行文件reader 3.自定义FieldSetMapper 4.读跨多行文件processor 5.读跨多行文件writer 写在前面 ...

  9. visio2013跨线问题

    问题如下图: 如上图所示,跨线让一幅辛苦绘制的图显得不那么好看,此时就需要将跨线去除掉. 方法: [设计]->[连接线]->[显示跨线],如果[显示跨线]前面的√存在,则会显示跨线,就和文 ...

最新文章

  1. matlab试用版的user id,免费试用MATLAB
  2. 在 Laravel 应用中使用 pjax 进行页面加速
  3. ArcGIS Javascript API 加载高德在线地图扩展
  4. 计算机网络hdcp是什么意思,为什么显卡面板显示此显示器不支持HDCP是怎么回事...
  5. 把ICDAR2019-LSVT原始数据集转为REC任务识别数据
  6. Lighthouse
  7. pythongui入门实例大全详细教程全_python简单进阶之GUI:PySimpleGUI案例
  8. java出现令牌语法错误_java – 令牌上的语法错误
  9. 普通话测试软件推荐,练普通话的软件哪个好 专门练普通话的软件推荐
  10. 频率单位转换 hz cpd cph
  11. pyscripter与python的关系_Pyscripter是python下一个非常流行的开源IDE
  12. python中线条颜色_python – 在pandas中指定线条颜色
  13. matlab R2013a 生成exe 脱离matlab开发环境运行
  14. java uninstall tool_java卸载工具|java卸载工具(JavaUninstallTool)下载v1.1.0.0 - 欧普软件下载...
  15. oracle中正则表达式规则,Oracle SQL 正则表达式
  16. Object类的常用方法
  17. 国科大移动互联网技术考试
  18. Multi-Horizon Time Series Forecasting with Temporal Attention Learning
  19. c语言链表增加新节点,C语言 链表的创建,以及节点的增加和删除
  20. PowerShell and PsExec Remote Call

热门文章

  1. mysql php 封装类_市面上几款常见的微信开发框架对比(PHP和JAVA)
  2. linux添加匿名用户,vsftpd3.0之匿名用户配置
  3. 网络数据嗅探工具HexInject
  4. android关闭触摸声音,如何在Android中以编程方式禁用触摸时的振动和声音?
  5. 手机连接服务器传文件在哪里,手机云服务器传文件在哪里
  6. oracle索引本地打钩,Oracle
  7. python etree htm参数_python笔记1--lxml.etree解析html
  8. java线程池拒绝策略_Java核心知识 多线程并发 线程池原理(二十三)
  9. iOS友盟推送发送失败
  10. 脑电分析系列[MNE-Python-8]| 参考电极简介