BackGroundWorker解決 執行緒間操作無效: 從不是建立控制元件的執行緒訪問它
阿新 • • 發佈:2019-02-08
在程式設計中經常會遇到在一個按鈕中執行復雜操作,並將複雜操作最後返回的值加入一個ListView或ComboBox中候選。這個時候程式會卡,當程式設計師將這些卡程式碼放進執行緒(Thread)中後發現當對控制元件操作時出現“執行緒間操作無效: 從不是建立控制元件的執行緒訪問它”異常。
為什麼.net不讓我們跨執行緒操作控制元件,這是有好處的。因為如果你的執行緒多了,那麼當兩個執行緒同時嘗試將一個控制元件變為自己需要的狀態時,執行緒的死鎖就會發生。但是難道就是因為這個原因,我們就只能讓程式卡著麼?當然不是,這裡教大家一個解決方案:用BackGroundWorker
這裡通過一個例項來告訴大家BackGroundWorker的用法。
首先我們先定義一個BackGroundWorker,大家可以去面板上拖一個,也可以自己手工定義一個。
this.backgroundWorker_Combo.WorkerSupportsCancellation =true;//設定能否取消任務this.backgroundWorker_Combo.DoWork +=new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker_Combo_DoWork);//讓backgroundWorker做的事
this.backgroundWorker_Combo.RunWorkerCompleted +=new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker_Combo_RunWorkerCompleted);//當backgroundWorker做完後發生的事件 如果是從面板上拖的,那麼請在DoWork事件上雙擊,新增那些你想在背景執行緒中執行的程式碼,也就是那些可能會讓你卡的程式碼。
然後再在RunWorkerCompleted事件上雙擊,新增那些你想往控制元件裡操作的程式碼。
這裡有一個開發例項,講的是實現類似Google搜尋中下拉列表的實現。其思路是在DoWork中搜索資料庫,在Completed中將搜出來的東西放進去。
本文需要一個backgroundWorker,一個ComboBox控制元件
/**////<summary>
/// 接受從DLL搜出來的專案
///</summary>
privatestring[] global_ListItem;
privatevoid backgroundWorker_Combo_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{//如果陣列中有東西,那麼加入ComboBox
if (global_ListItem.Length>0)
{
this.comboBox_App.Items.Clear();
this.comboBox_App.Items.AddRange(global_ListItem);
}
}
privatevoid backgroundWorker_Combo_DoWork(object sender, DoWorkEventArgs e)
{
global_ListItem = Form_Setting.Global_DBC.SimilarFilter(x); //這是一個DLL中的方法,用於查詢所有以X打頭的專案,並放入一個數組中
}
privatevoid comboBox_App_TextChanged(object sender, EventArgs e)
{//當用戶鍵入一個字母時去資料庫查
ComboBox cb = sender as ComboBox;
if (cb.Text.Length==1)
{
x = cb.Text[0];
this.backgroundWorker_Combo.RunWorkerAsync();
}
}
第二種簡單的方法是運用CheckForIllegalCrossThreadCalls,在主窗體的建構函式中加上 Control.CheckForIllegalCrossThreadCalls = false; 即可