1. 程式人生 > >BackGroundWorker解決 執行緒間操作無效: 從不是建立控制元件的執行緒訪問它

BackGroundWorker解決 執行緒間操作無效: 從不是建立控制元件的執行緒訪問它

在程式設計中經常會遇到在一個按鈕中執行復雜操作,並將複雜操作最後返回的值加入一個ListView或ComboBox中候選。這個時候程式會卡,當程式設計師將這些卡程式碼放進執行緒(Thread)中後發現當對控制元件操作時出現“執行緒間操作無效: 從不是建立控制元件的執行緒訪問它”異常。
        為什麼.net不讓我們跨執行緒操作控制元件,這是有好處的。因為如果你的執行緒多了,那麼當兩個執行緒同時嘗試將一個控制元件變為自己需要的狀態時,執行緒的死鎖就會發生。但是難道就是因為這個原因,我們就只能讓程式卡著麼?當然不是,這裡教大家一個解決方案:用BackGroundWorker
        這裡通過一個例項來告訴大家BackGroundWorker的用法。
        首先我們先定義一個BackGroundWorker,大家可以去面板上拖一個,也可以自己手工定義一個。

this.backgroundWorker_Combo =new System.ComponentModel.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控制元件
staticchar x;
        
/**////<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; 即可