C#中跨線程訪問控件的實現(xiàn)方法
一、簡述
C#中不允許跨線程直接訪問界面控件,即一個線程中如主線程創(chuàng)建的控件不允許被其他線程例如子線程直接訪問,如果直接訪問或設置屬性則會爆出“調(diào)用線程無法訪問此對象,因為另一個線程擁有該對象”等類似錯誤。
在一個線程中設置其他線程所有的控件屬性通常有兩種方法,一是設置System.Windows.Forms.Control的CheckForIllegalCrossThreadCalls屬性值為false,表示不對錯誤線程的調(diào)用進行捕捉,這種方法只對winforms界面框架有效,在WPF中無法設置該屬性,只能使用第二種方法。
第二種方法是通過委托來實現(xiàn)控件屬性設置,需要通過Invoke或BeginInvoke來實現(xiàn),Invoke表示同步,BeginInvoke表示異步,下面列舉了在winforms中和WPF兩種界面框架中跨線程訪問控件的代碼示例。
二、Winforms中跨線程訪問控件
一般的委托方法示例代碼如下:
delegate void delegateSetText(string str);//定義一個委托 private void SetText(string str) { if (InvokeRequired)//判斷是否是被其他線程調(diào)用 { delegateSetText delegatesetText01 = new delegateSetText(SetText); Invoke(delegatesetText01, new object [] {str}); return; } textBox01.Text = str; }
也可以采用匿名代理的方式,示例代碼如下:
delegate void delegateSetText(string str);//定義一個委托 private void SetText(string str) { delegateSetText delegatesetText01 = delegate(string str01) { textBox01.Text = str01; } Invoke(delegatesetText01, new object [] {str}); }
三、WPF中跨線程訪問控件
在WPF中跨線程訪問控件需要使用Dispatcher。Dispatcher是WPF中的線程調(diào)度管理器,用在子線程刷新主線程(UI線程)(比如綁定的時候,屬性更新的時候),在子線程里面起一個dispatcher,將工作項目調(diào)度到 UI 線程,讓主線程調(diào)度刷新UI的代碼。示例代碼如下:
private void SetText(string str) { if (!Dispatcher.CheckAccess())//判斷是否是被其他線程調(diào)用 { Dispatcher.Invoke(() => SetText(str)); return; } textBox01.Text = str; }
【注】
避免”在創(chuàng)建窗口句柄之前,不能在控件上調(diào)用 Invoke 或 BeginInvoke。“錯誤。
一個Form窗體必須完全創(chuàng)建完成,才能調(diào)用它自身或它上面控件的Invoke或BeginInvoke。
經(jīng)測試,窗體的構(gòu)造函數(shù)內(nèi)的InitializeComponent()的執(zhí)行完成時,窗體并未創(chuàng)建完成;窗體的構(gòu)造函數(shù)執(zhí)行完成時,窗體也并未創(chuàng)建完成;
在form.show()后,窗體是已經(jīng)創(chuàng)建完成了。
另外,可以在調(diào)用Invoke()前,判斷一下 if (form.Created),以避免此處異常中斷。
最后
到此這篇關(guān)于C#中跨線程訪問控件的方法的文章就介紹到這了,更多相關(guān)C#跨線程訪問控件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
.Net多進程通信共享內(nèi)存映射文件Memory?Mapped
這篇文章主要介紹了.Net多進程通信共享內(nèi)存映射文件Memory?Mapped的使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-04-04