出處:
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 使用控制...