看了几篇文章,有了大概的理解,解决如下问题:
1、理解事情和委托是怎么来的,为什么要有委托,委托结合事情的魅力所在;
2、UI线程中怎么正确调用同步委托或异步委托;Invoke和BeginInvoke的区别是什么;Control.invoke和delegate.invoke有什么区别?
事件和委托原理的理解解析:
对.net事件的看法
Invoke和BeginInvoke的深入理解和解析:
UI线程中的同步和异步调用、怎么调用,多线程中各个方法的执行顺序:
最后我总结了下实际在后台线程更新UI线程控件的方法:
- private Thread invokeThread;
- private delegate void invokeDelegate();
- private void StartMethod(){
- //C代码段......
- Control.Invoke(new invokeDelegate(invokeMethod));
- }
- private void invokeMethod(){
- //E代码段,更新UI界面
- }
- private void butInvoke_Click(object sender, EventArgs e) {
- //A代码段.......
- invokeThread = new Thread(new ThreadStart(StartMethod));
- invokeThread.Start();
- //B代码段......
- }
上面的模板中,由于Control.Invoke调用下面么样其他待执行的代码,所以使用Control.BeginInvoke也是同样效果的。
在第3篇引用博文中,按作者的思路,使用Control.BeginInvoke有时反而会导致UI线程更新混乱问题。
而且总的来说,上面的文章帮助理解这些线程实现机制,实际使用时,可以考虑使用BackgroundWorker 类,其MSDN上介绍如下:
BackgroundWorker 类允许您在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
若要在后台执行耗时的操作,请创建一个 BackgroundWorker ,侦听那些报告操作进度并在操作完成时发出信号的事件。可以通过编程方式创建 BackgroundWorker ,也可以将它从“工具箱” 的“组件” 选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 BackgroundWorker ,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
若要设置后台操作,请为 DoWork 事件添加一个事件处理程序。在此事件处理程序中调用耗时的操作。若要启动该操作,请调用 RunWorkerAsync 。若要收到进度更新通知,请对 ProgressChanged 事件进行处理。若要在操作完成时收到通知,请对 RunWorkerCompleted 事件进行处理。
注意: |
---|
您必须非常小心,确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。 BackgroundWorker 事件不跨 AppDomain 边界进行封送处理。请不要使用 BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。 |