教你如何解決“線程間操作無效: 從不是創建控件的線程訪問它”

在編程中經常會遇到在一個按鈕中執行復雜操作,並將複雜操作最後返回的值加入一個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控件
        static char x;         /**//// <summary>         /// 接受從DLL搜出來的項目         /// </summary>         private string[] global_ListItem;         private void 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);             }         }         private void backgroundWorker_Combo_DoWork(object sender, DoWorkEventArgs e)         {             global_ListItem = Form_Setting.Global_DBC.SimilarFilter(x); //這是一個DLL中的方法,用於查找所有以X打頭的項目,並放入一個數組中         }         private void 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();             }         }
        那麼是不是用Thread就不行呢?其實不是的,.net中也有線程安全的控件訪問。如果想了解如何用thread來解決“線程間操作無效: 從不是創建控件的線程訪問它”,建議大家看看這篇文章:         http://www.cnblogs.com/imissherso/archive/2007/01/28/632480.html         此文從非線程安全,線程安全和BackgroundWork三種方法討論了這個問題,而我這裏是針對第三個問題深入解釋了下,希望能夠對大家帶來幫助。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章