WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 C
WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用
Control 不能在創建它的 Thread 之外被調用。但可以通過 invoke 來保證 Control 線程安全。
在跨線程更新的時候,Control 會檢查 CurrentThread 是否為創建 Control 的線程,并報錯!
示例代碼如下:?
示例代碼 private?void?btnStart_Click(object?sender,?EventArgs?e){
?????//注意:特地不使用?Timer?控件
?????Thread?thread?=?new?Thread(Fun);
?????thread.Start(DateTime.Now.ToString());
}
//報錯:線程間操作無效:?從不是創建控件“lblTime”的線程訪問它。
private?void?Fun(object?datetime)
{
?????lblTime.Text?=?(string)datetime;
}
最簡單的解決方式是在程序代碼中添加如下屬性:
????????Control.CheckForIllegalCrossThreadCalls = false;
在多線程編程中,我們經常要在工作線程中去更新界面顯示,而在多線程中直接調用界面控件的方法是錯誤的做法,Invoke 和 BeginInvoke 就是為了解決這個問題而出現的,使你在多線程中安全的更新界面顯示。
將要做的事情放在工作線程中執行,而將對純粹的界面更新放到 UI 線程中去做,這樣也就達到了減輕 UI 線程負擔的目的。
?
使用?BeginInvoke?方法解決該問題的代碼如下:
using?System.Collections.Generic;
using?System.ComponentModel;
using?System.Data;
using?System.Drawing;
using?System.Text;
using?System.Windows.Forms;
using?System.Threading;
namespace?Invoke_Test
{
????public?partial?class?Form1?:?Form
????{
????????//private?System.Windows.Forms.Label?lblTime;
????????//private?System.Windows.Forms.Button?btnStart;
????????public?Form1()
????????{
????????????InitializeComponent();
????????????//?解決方式一
????????????//?Control.CheckForIllegalCrossThreadCalls?=?false;
????????}
????????private?void?btnStart_Click(object?sender,?EventArgs?e)
????????{
????????????string?arg?=?DateTime.Now.ToString();
????????????//?注意:創建子線程間接調用
????????????Thread?thread?=?new?Thread(FunStart);
????????????thread.Start(arg);?//arg?給方法傳參??
????????}
????????//?定義調用方法的委托
????????delegate?string?FunDelegate(string?str);
????????//?注意:特地使用?FunStart?方法模擬間接調用
????????private?void?FunStart(object?obj)
????????{
????????????//?要調用的方法的委托
????????????FunDelegate?funDelegate?=?new?FunDelegate(Fun);
????????????/*========================================================
?????????????*?使用this.BeginInvoke方法
?????????????*?(也可以使用this.Invoke()方法)
????????????========================================================*/
????????????//?this.BeginInvoke(被調用的方法的委托,要傳遞的參數[Object數組])
????????????IAsyncResult?aResult?=?this.BeginInvoke(funDelegate,obj.ToString());
????????????//?用于等待異步操作完成(-1表示無限期等待)
????????????aResult.AsyncWaitHandle.WaitOne(-1);
????????????//?使用this.EndInvoke方法獲得返回值
????????????string?str?=?(string)this.EndInvoke(aResult);
????????????MessageBox.Show(str.ToString());
????????}
????????//?真正需要執行的方法
????????private?string?Fun(string?datetime)
????????{
????????????lblTime.Text?=?(string)datetime;
????????????return?"委托的返回值";
????????}
????}
}
Control.InvokeRequired 屬性:當前線程不是創建控件的線程時為 true。
也可以認為,在 new Control() 的時候,Control 用一個變量記錄下了當前線程,在調用 InvokeRequired 時,返回當前線程是否不等于 new 的時候記錄下來的那個線程。
?
Control.Invoke 和 Control.BeginInvoke 就是“發短信”的方法,如果使用 Control.Invoke 發短信,那么甲線程就會像個癡情的漢子,一直等待著乙線程的回音,而如果使用 Control.BeginInvoke 發送短信,那發完短信后,甲線程就會忙活自己的,等乙線程處理完再來瞧瞧。
推薦閱讀:WinForm二三事(三)Control.Invoke&Control.BeginInvoke?
示例代碼:Invoke_Test?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 C的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用汇编的眼光看C++(之拷贝、赋值函数)
- 下一篇: 音视频编解码的一些源代码