有時在程序中需要一些占用資源很大的處理,比如數據庫更新操作,在一些比較簡單的情況可以使用Application.DoEvent()方法,解決UI界面不友好的問題,但是如果是一些復雜的情況就沒辦法了,比如在處理中點擊按鈕以暫停當前處理。這時用第一個方法就不好了(因為按鈕不會顯示被按下)

         這個時候就需要用異步委托或者啟動另一個線程去處理復雜的聚集操作,但是如果在工作線程中需要更新用戶的UI界面,并且在點擊按鈕后要停止那些工作線程,需要如何進行處理呢?

      解決第一個問題的方法,就是在工作線程中調用Control.BeginInvoke方法(Control.Invoke用于同步調用,該調用阻塞當前線程直到UI返回結果)。

         Control.BeginInvoke方法有一個重載方法


         public IAsyncResult BeginInvoke(Delegate);

         public virtual IAsyncResult BeginInvoke(Delegate, object[]);


         第二個方法傳遞的是委托的參數

         在工作線程中調用的方法中可以先判斷是否在UI線程中,如果是就進行UI操作,如果不是在進行異步調用(control.begininvoke),在這里需要用到一個判斷條件:Control.InvokeRequired,這個屬性如果返回False,則代表當前就是UI線程,否則為工作線程

舉個例子:

private void MakeLogs(string body)
                   {
                            
if (InvokeRequired == false)
                            {
                                     ListViewItem lvi 
= new ListViewItem(DateTime.Now.ToString());
                                     lvi.SubItems.Add(body);
                                     
if (lvContent.Items.Count == 200)
                                     {
                                               lvContent.Items.RemoveAt(lvContent.Items.Count
-1);
                                     }
                                     lvContent.Items.Insert(
0,lvi);
                            }
                            
else
                            {
                                     MakeLogDelegate makeLogs 
= new MakeLogDelegate(MakeLogs);
                                     BeginInvoke(makeLogs,
new object[]{body});
                            }
                   }



         解決第二個問題的方法是:在工作線程中周期性的檢查按鈕狀態。比如界面有個“取消”按鈕,當用戶點擊這個按鈕后,將狀態變量置位,然后工作線程就去檢查這個狀態變量,如果發現取消狀態被置位,則停止當前線程

         舉個例子:

 

private void CheckState(out bool cancel)
                   {
                            
if (InvokeRequired == false)              
                                //在此需要判斷線程是否為UI線程,因為如果在工作
                                //線程上,會導致兩個線程(UI Thread、Work Thread)共同訪問一個變量
                            {
                                     cancel 
= (m_state==ImportState.canceled);
                            }
                            
else
                            {
                                    object outCancel = false;                 //此處的用意是:由于bool類型是值類型,
                                     //在傳入后進行裝箱操作,導致其值不變化
                                     CheckStateDelegate checkStateDelegate = new CheckStateDelegate(CheckState);
                                     Invoke(checkStateDelegate,
new object[]{outCancel});
                                      
//此處用Invoke而不用BeginInvoke的原因是:需要確實得到狀態才
                                      //能做返回,所以不能用異步調用
                                     cancel = (bool)outCancel;
                            }
                   }