C#中跨线程操作控件

6 篇文章 0 订阅

一、前面的话

对于一些耗时型操作(如文件下载),让主线程去处理不是明智的选择,虽然这样做会使得程序开发起来很简单。因为WinForm 程序设计的准则之一就是Responsive ,即让用户觉得程序一直在工作,而不是感觉它在罢工(呵呵,事实上,程序不会罢工,只是你没给他表现得机会,如果它有情感,会觉得委屈死)。.Net FrameWork 支持在程序用应用线程编程,这可以很好的解决上述问题,不过有时候直接使用ThreadThreadstart 显得有些繁琐也没必要,为此.Net Framework 提供了BackgroundWorker 组件来应付一些简单的应用环境。

本文将分别对上述两种情况的跨线程操作控件方法进行阐述。

二、 BackgroundWorker 下的跨线程操作控件

BackgroundWorker 是个很好的伙计,因为它可以忙你搞定许多脏活累活。具体的讲,它可以自动的帮你创建工作线程,可以在工作时把工作的进展情况告诉给你,可以在工作完成时通知并帮你做一些收尾的工作,当你觉得他很烦的时候,你还可以随时让他停下来。

BackgroundWorker 组件提供了三个事件:DoWorkProgressChangedRunWorkerCompletedDowork 顾名思义是用来处理工作业务的,在这里面加入你想让工作线程在后台处理的代码即可。但是在这个事件中不能加入跨线程操作的代码。如下图,当我试图改变Label.Text 的值时,抛出了异常信息:

 

不过这里有个例外 ,就是对于ToolStrip 及其从该类继承过来的容器控件,某些在该容器上的控件(如StatusLabel )可以在工作线程中直接操作 。至于为啥,我没有去深究,不过根据图中的提示信息,一个很合理的解释就是这类控件和BackgroundWorker 由同一个线程创建。

ProgressChanged RunWorkerCompleted 事件分别用来报告工作线程的工作情况和在工作线程结束后进行一些操作。这两个事件都支持跨线程操作控件 。下面通过一个简单的实例进行验证。

用程序实现将一个目录中的文件拷贝至另外一个目录。

1 .程序界面设计如下:

 

2 .工作流程:(1 )设置源目录和目标目录(2 )拷贝文件,在ListView 中显示拷贝信息,更新状态栏中的进度条和当前处理文件信息(3 )拷贝过程结束后,用MessageBox 提示拷贝文件数量,同时清空源目录和目标目录信息。

3 .代码实现

 

 

4. 运行结果

 

三、 Thread/ThreadStart 下的跨线程操作控件

在一些情况下,Thread/ThreadStart 也是有一定市场的,特别在工作线程很多的情况下,显得尤为突出。事实上,在这种环境下要实现上述的例子并不难,代码也没有增加多少,前提是你必须理解Control.Invoke 方法。 该方法在MSDN 上的解释是:在拥有此控件的基础窗口句柄的线程上执行委托。如果你注意到了第一张图片显示的异常信息,你会很快理解这个方法的重大意义。它可以让工作线程的中委托在主线程中执行! 因此实现上述例子的思路就是,在工作线程中使用委托来执行操作控件的方法,然后用主窗口的Invoke 方法调用!

为了实现BackgroundWorker ProgressChanged RunWorkerCompleted 事件,定义了ReportProcessInfo 委托和DoneAfterCompleted 委托。

主要代码如下:

 

 

运行结果如下:

 

四、结尾

代码中的InvokeRequired 用于判断该段代码是否是在其他线程中委托调用的,如果为真,就需要在本线程中重新创建一个该委托的实例,并用Invoke 方法调用它,让这段代码在本线程中调用。

当代码中需要对多个控件进行操作,最好使用FormInvokeRequired 来判断,并使用FormInvoke 方法调用新建的委托实例。当只对某个控件操作时,就可以只用该控件的InvokeRequiredInvoke 。比如tbSource, 就可用 tbSource.InvokeRequired tbSource.Invoke

下面是本文相关代码

Thread_ThreadStart方式

BackgroundWorker方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值