有時(shí)在程序中需要一些占用資源很大的處理,比如數(shù)據(jù)庫(kù)更新操作,在一些比較簡(jiǎn)單的情況可以使用Application.DoEvent()方法,解決UI界面不友好的問(wèn)題,但是如果是一些復(fù)雜的情況就沒(méi)辦法了,比如在處理中點(diǎn)擊按鈕以暫停當(dāng)前處理。這時(shí)用第一個(gè)方法就不好了(因?yàn)榘粹o不會(huì)顯示被按下)

         這個(gè)時(shí)候就需要用異步委托或者啟動(dòng)另一個(gè)線(xiàn)程去處理復(fù)雜的聚集操作,但是如果在工作線(xiàn)程中需要更新用戶(hù)的UI界面,并且在點(diǎn)擊按鈕后要停止那些工作線(xiàn)程,需要如何進(jìn)行處理呢?

      解決第一個(gè)問(wèn)題的方法,就是在工作線(xiàn)程中調(diào)用Control.BeginInvoke方法(Control.Invoke用于同步調(diào)用,該調(diào)用阻塞當(dāng)前線(xiàn)程直到UI返回結(jié)果)。

         Control.BeginInvoke方法有一個(gè)重載方法


         public IAsyncResult BeginInvoke(Delegate);

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


         第二個(gè)方法傳遞的是委托的參數(shù)

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

舉個(gè)例子:

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});
                            }
                   }



         解決第二個(gè)問(wèn)題的方法是:在工作線(xiàn)程中周期性的檢查按鈕狀態(tài)。比如界面有個(gè)“取消”按鈕,當(dāng)用戶(hù)點(diǎn)擊這個(gè)按鈕后,將狀態(tài)變量置位,然后工作線(xiàn)程就去檢查這個(gè)狀態(tài)變量,如果發(fā)現(xiàn)取消狀態(tài)被置位,則停止當(dāng)前線(xiàn)程

         舉個(gè)例子:

 

private void CheckState(out bool cancel)
                   {
                            
if (InvokeRequired == false)              
                                //在此需要判斷線(xiàn)程是否為UI線(xiàn)程,因?yàn)槿绻诠ぷ?br />                                 //線(xiàn)程上,會(huì)導(dǎo)致兩個(gè)線(xiàn)程(UI Thread、Work Thread)共同訪問(wèn)一個(gè)變量
                            {
                                     cancel 
= (m_state==ImportState.canceled);
                            }
                            
else
                            {
                                    object outCancel = false;                 //此處的用意是:由于bool類(lèi)型是值類(lèi)型,
                                     //在傳入后進(jìn)行裝箱操作,導(dǎo)致其值不變化
                                     CheckStateDelegate checkStateDelegate = new CheckStateDelegate(CheckState);
                                     Invoke(checkStateDelegate,
new object[]{outCancel});
                                      
//此處用Invoke而不用BeginInvoke的原因是:需要確實(shí)得到狀態(tài)才
                                      //能做返回,所以不能用異步調(diào)用
                                     cancel = (bool)outCancel;
                            }
                   }