invokeRequired屬性和 invoke()方法

zt: http://www.x2blog.cn/jinhong618/?tid=22389 c#

 

問:安全

f (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(LoadGlobalImage));
return;
}

 

是什麼意思 函數

答: c#中禁止跨線程直接訪問控件,InvokeRequired是爲了解決這個問題而產生的ui

當一個控件的InvokeRequired屬性值爲真時,說明有一個建立它之外的線程想訪問它,此時它將會在內部調用new MethodInvoker(LoadGlobalImage)來完成下面的步驟,這個作法保證了控件的安全,你能夠這樣理解,有人想找你借錢,他能夠直接在你的錢包中拿,這樣太不安全,所以必須讓別人先要告訴你,你再從本身的錢包把錢拿出來借給別人,這樣就安全了this

 

 

another:spa

在設計中爲了讓界面與邏輯分離,個人作法是使用事件,界面只要響應事件來處理界面的顯示就好了。而事件在邏輯處理中可能由不一樣的線程引起,這些事件的響應方法在修改界面中的控件內容時便會引起一個異常。線程

這時就用到了Control.InvokeRequired 屬性 與Invoke方法。設計

MSDN中說:
獲取一個值,該值指示調用方在對控件進行方法調用時是否必須調用 Invoke 方法,由於調用方位於建立控件所在的線程之外的線程中。 
若是控件的 Handle 是在與調用線程不一樣的線程上建立的(說明您必須經過 Invoke 方法對控件進行調用),則爲 true;不然爲 false。
Windows 窗體中的控件被綁定到特定的線程,不具有線程安全性 。所以,若是從另外一個線程調用控件的方法,那麼必須使用控件的一個 Invoke 方法來將調用封送到適當的線程。該屬性可用於肯定是否必須調用 Invoke 方法,當不知道什麼線程擁有控件時這頗有用。code

下面來講下這個的用法(個人通常作法):
首先定義一個委託,與這個事件處理函數的簽名同樣委託,固然直接使用該事件的委託也是能夠的,如:blog

private delegate void InvokeCallback( string msg);

而後就是判斷這個屬性的值來決定是否要調用Invoke函數:

 void m_comm_MessageEvent( string msg)
 {
 if (txtMessage.InvokeRequired)
 {
 InvokeCallback msgCallback = new InvokeCallback(m_comm_MessageEvent);
 txtMessage.Invoke(msgCallback, new object [] { msg } );
 } 
 else 
 {
 txtMessage.Text = msg;
 } 
 }

 

說明:這個函數就是事件處理函數,txtMessage是一個文本框。
這樣就作到了窗體中控件的線程安全性。

 

------------------

InvokeRequired 當前線程不是建立控件的線程時爲true
好比你能夠本身開一個Thread,或使用Timer的事件來訪問窗體上的控件的時候,在線程中窗體的這個屬性就是True的。

簡單的說,若是有兩個線程,Thread A和Thread B,而且有一個Control c,是在Thread A裏面new的。
那麼在Thread A裏面運行的任何方法調用c.InvokeRequired都會返回false。
相反,若是在Thread B裏面運行的任何方法調用c.InvokeRequired都會返回true。
是不是UI線程與結果無關。(一般Control所在的線程是UI線程,可是能夠有例外)

也能夠認爲,在new Control()的時候,control用一個變量記錄下了當前線程,在調用InvokeRequired時,返回當前線程是否不等於new的時候記錄下來的那個線程。

--------------------

我理解:若是InvokeRequired==true表示其它線程須要訪問控件,那麼調用invoke來轉給控件owner處理。

相關文章
相關標籤/搜索