Winform中的线程Threading in WinForms(翻译)

本文翻译自:

Threading in .NET and WinForms - CodeProject

本文是个人的理解,如有不对的地方,请指教

我们都知道,在子线程不能直接更新UI线程中的控件,不然会报错,这是Window中的一个规则(原话:A rule in Windows is that "a control created on one thread cannot be modified in another thread"),子线程想要更新UI线程中的控件,那就只有通过发消息的方式。任何Window程序都有两个队列,Post Message队列和Send Message队列,而主线程专门处理这两个队列的消息并更新UI控件。而这两个消息队列的区别是,发送到Send Message队列的线程(记为a),把消息发送到队列后,该a线程会堵塞并等主线程执行完发过去的消息后,该线程a才会往下执行。另外一个发送到Post Message队列的线程(记为b),把消息发送到队列后,b线程不用等主线程处理完毕发过去的消息就会继续往下执行线程后面的逻辑(即不会堵塞线程b)。

想要在子线程中更新UI线程,winform的Control控件本身已经提供了3个方法,如下:

Invoke发送的是 SendMessage(即会堵塞),而BeginInvoke发送的是Post Message (即不会堵塞),而EndInvoke是处理BeginInvoke的回调信息,这里不讨论。

1   Control.Invoke提供两个方法重载,如下:

 可以看到方法参数中都有一个Delegate委托,具体例子如下:

Winform中的线程Threading in WinForms(翻译)_第1张图片

 通过开启线程的方式执行RunInThread方法,该子线程记为a,需要注意的是,AddControl方法和RunInThread方法不在同一个线程中执行,RunInThread方法在子线程a中执行,而AddControl方法在UI线程中执行(这里是主线程)。由于Invoke方法会堵塞线程a,所以会先执行AddControl方法后才会弹出"Hello"的提示框。

2  Control.BeginInvoke提供两个方法重载,如下:

 还是以例子的方式进行解读,例子如下:

Winform中的线程Threading in WinForms(翻译)_第2张图片

 还是以启动线程的方式执行RunInThread方法,该子线程记录为a,需要注意的是,AddControl方法和RunInThread方法也是不在同一个线程中执行,RunInThread方法在子线程a中执行,而AddControl方法在UI线程中执行(这里是主线程)。由于Invoke方法不会堵塞线程a,所以会先弹出"Hello"的提示框再执行AddControl方法。

3  为了加深理解,一起来看一下下面程序的执行结果

例子3.1

Winform中的线程Threading in WinForms(翻译)_第3张图片

 Form_Load中的for循环和AddControl中的for循环并不会并行执行,为什么呢?因为Form_Load中的for循环和AddControl中的for循环都在主线程执行(即在同一个线程中执行),所以我们会先看到Form_Load中的for循环执行完毕后,才会继续执行AddControl方法中的for循环。

例子3.2 

Winform中的线程Threading in WinForms(翻译)_第4张图片

 同样的,Form_Load中的for循环和AddControl中的for循环并不会并行执行,Form_Load中的for循环和AddControl中的for循环都在主线程执行(即在同一个线程中执行),由于Invoke方法有堵塞的作用,所以会先执行AddControl中的for循环,再执行Form_Load中的for循环。

4  Control.InvokeRequired属性

先看一下下面的代码:

Winform中的线程Threading in WinForms(翻译)_第5张图片

AddControl方法在UI线程中执行(主线程),即和Form_Load方法同一个线程,所以并不需要通过Control.Invoke方法更新UI线程,所以在实际工作编程中,往往在很多地方都看到如下的写法:

Winform中的线程Threading in WinForms(翻译)_第6张图片

 是不是有种似曾相识的感觉,没错,就是根据Control.InvokeRequired属性判断是否需要通过Control.Invoke的方式更新UI线程。

好了,本文到此结束,要上班了,写得有点匆忙哈

你可能感兴趣的:(C#编程,Winform,UI线程,子线程,InvokeRequired,C#)