C 中跨執行緒更新UI

2021-07-27 15:47:54 字數 3012 閱讀 6523

出處:

c#winform程式設計中,跨執行緒直接更新ui控制項的做法是不正確的,會時常出現「執行緒間操作無效: 從不是建立控制項的執行緒訪問它」的異常。處理跨執行緒更新winform ui控制項常用的方法有4種: 

1. 通過ui執行緒的synchronizationcontext的post/send方法更新;

2. 通過ui控制項的invoke/begaininvoke方法更新;

3. 通過backgroundworker取代thread執行非同步操作;

4. 通過設定窗體屬性,取消執行緒安全檢查來避免"跨執行緒操作異常"(非執行緒安全,建議不使用)。

下文中對以上3種方法應用進行舉例說明,希望能對初識c# winform的同學們有些幫助。

成文表分享交流之意,惶恐水平有限,文中 理解和表述有錯誤之處還請大家多被批評指正。

1.

用法: 

//共分三步

//第一步:獲取ui執行緒同步上下文(在窗體建構函式或formload事件中)

//////ui執行緒的同步上下文 /// synchronizationcontext m_synccontext = null; public form1() //第二步:定義執行緒的主體方法 //////執行緒的主體方法 ///

///private voidsettextsafepost(object text) //之後,啟動執行緒 //////啟動執行緒按鈕事件 ///

//////

private void setsafepostbtn_click(object sender, eventargs e)

在本質上,向ui執行緒傳送的訊息並是不簡單資料,而是一條委託呼叫命令。

2.通過ui控制項的invoke/begaininvoke方法更新

用法:與方法1類似,可分為三個步驟。

//共分三步

//第一步:定義委託型別

//將text更新的介面控制項的委託型別 delegate voidsettextcallback(string text); //第二步:定義執行緒的主體方法 //////執行緒的主體方法 ///

///private voidsettext(string text) settextcallback d = new settextcallback(settext);this.textbox1.invoke(d, new object ); } else } //之後,啟動執行緒 //////啟動執行緒按鈕事件 ///

//////

private void settextsafebtn_click( object sender, eventargs e)

說明:這個方法是目前跨執行緒更新ui使用的主流方法,使用控制項的invoke/begaininvoke方法,將委託轉到ui執行緒上呼叫,實現執行緒安全的更新。原理與方法1類似,本質上還是把執行緒中要提交的訊息,通過控制項控制代碼呼叫委託交到ui執行緒中去處理。

解決窗體關閉時出現「訪問已釋放控制代碼「的異常 部分**參考 -事理同學的文章 。

3.

用法:

//共分三步

//第一步:定義backgroundworker物件,並註冊事件(執行執行緒主體、執行ui更新事件)

private backgroundworker backgroundworker1 =null; public form1()

說明:通過設定checkforillegalcrossthreadcalls屬性,可以指示是否捕獲執行緒間非安全操作異常。該屬性值預設為ture,即執行緒間非安全操作是要捕獲異常的("執行緒間操作無效"異常)。通過設定該屬性為false簡單的遮蔽了該異常。control.checkforillegalcrossthreadcalls的注釋如下

//

//摘要:

//獲取或設定乙個值,該值指示是否捕獲對錯誤執行緒的呼叫,這些呼叫在除錯應用程式時訪問控制項的 system.windows.forms.control.handle

//屬性。 // //返回結果: //如果捕獲了對錯誤執行緒的呼叫,則為 true;否則為 false。 [editorbrowsable(editorbrowsablestate.advanced)] [designerserializationvisibility(designerserializationvisibility.hidden)] [srdescription("controlcheckforillegalcrossthreadcalls")] [browsable(false)] public static bool checkforillegalcrossthreadcalls

文中介紹的4種方法,前三種是執行緒安全的 ,可在實際專案中因地制宜的使用。最後一種方法是非執行緒安全的,初學者可以實驗體會但不建議使用它。

下面列表對比一下這四種方法 

方法執行緒安全支援非同步 / 同步

其他

ui synccontext更新

是post/send

盡量在窗體建構函式、 formload 中獲取同步上下文

控制項 invoke

是control.invoke/begaininvoke

注意檢查控制項控制代碼是否已釋放

backgroundworker 更新

是progresschanged、runworkercompleted

事件同步更新

報告進度

checkforillegalcrossthreadcalls

取消跨執行緒呼叫檢查

否同步更新

簡單,不建議使用

分類: 

c#

C 利用委託跨執行緒更新UI資料

在使用c 的過程中,難免會用到多執行緒,而用多執行緒之後,執行緒如何與介面互動則是乙個非常頭疼的問題。其實不僅僅是介面,一般情況下,我們往往需要獲得執行緒的一些資訊來確定執行緒的狀態。比較好的方式是用委託實現,看例子 注 本例利用委託和跨執行緒訪問技術,用介面上的兩個label控制項實時顯示執行緒的...

C 利用委託跨執行緒更新UI資料

在使用c 的過程中,難免會用到多執行緒,而用多執行緒之後,執行緒如何與介面互動則是乙個非常頭疼的問題。其實不僅僅是介面,一般情況下,我們往往需要獲得執行緒的一些資訊來確定執行緒的狀態。比較好的方式是用委託實現,看例子 注 本例利用委託和跨執行緒訪問技術,用介面上的兩個label控制項實時顯示執行緒的...

WPF跨執行緒更新UI控制項

1.預設情況下,在windows應用程式中,net framework不允許在乙個執行緒中直接操作另乙個執行緒中的控制項。winform中實現跨執行緒操作控制項的兩種方法 1 關閉執行緒安全檢查 control.checkforillegalcrossthreadcalls false 2 使用控制...