invoke和begininvoke 區別
一直對invoke和begininvoke的使用和概念比較混亂,這兩天看了些資料,對這兩個的用法和原理有了些新的認識和理解。
首先說下,invoke和begininvoke的使用有兩種情況:
control中的invoke、begininvoke。
delegrate中的invoke、begininvoke。
這兩種情況是不同的,我們這裡要講的是第1種。下面我們在來說下.net中對invoke和begininvoke的官方定義。
control.invoke(引數delegate)方法:在擁有此控制項的基礎視窗控制代碼的執行緒上執行指定的委託。
根據這兩個概念我們大致理解invoke表是同步、begininvoke表示非同步。
如果你的後台執行緒在更新乙個ui控制項的狀態後不需要等待,而是要繼續往下處理,那麼你就應該使用begininvoke來進行非同步處理。
如果你的後台執行緒需要操作ui控制項,並且需要等到該操作執行完畢才能繼續執行,那麼你就應該使用invoke。
我們來做乙個測試。
invoke 例子:
private
void
button1_click
(object sender,
eventargs e)
messagebox.
show
(thread.currentthread.
gethashcode()
.tostring()
+a);
}private
void
startmethod()
private
void
invokemethod()
結論:我們執行後,看下程式的執行順序,1aaa->3ccc和1bbb->1eee ->3ddd 。
解釋:主線程執行1aaa,然後1bbb和子執行緒3ccc同時執行,然後通過invoke來將invokemethod方法提交給主線程,然後子線 程等待主線程執行,直到主線程將invokemethod方法執行完成(期間必須等待主線程的任務執行完成,才會去執行invoke提交的任務),最後執 行子執行緒3ddd。
begininvoke 例子:
private
void
button1_click
(object sender,
eventargs e)
messagebox.
show
(thread.currentthread.
gethashcode()
.tostring()
+a);
}private
void
startmethod()
private
void
begininvokemethod()
結論: 我們執行後看看執行的結果:1aaa->1bbb和3ccc->1eee和3ddd。
解釋: 主線程執行1aaa,然後1bbb和子執行緒3ccc同時執行,然後通過begininvoke來將invokemethod方法提交給主線程,然後主線程執行1eee(主線程自己的任務執行完成), 同時子執行緒繼續執行3ddd。
通過這個兩段**的測試比較,我們會發現其實invoke和begininvoke所提交的委託方法都是在主線程中執行的,其實根據我invoke 和begininvoke的定義我們要在子執行緒中來看這個問題,在invoke例子中我們會發現invoke所提交的委託方法執行完成後,才能繼續執行 ddd;在begininvoke例子中我們會發現begininvoke所提交的委託方法後,子執行緒講繼續執行ddd,不需要等待委託方法的完成。 那麼現在我們在回想下invoke(同步)和begininvoke(非同步)的概念,其實它們所說的意思是相對於子執行緒而言的,其實對於控制項的呼叫總是由 主線程來執行的。我們很多人搞不清這個同步和非同步,主要還是因為我們把參照物選錯了。其實有時候光看概念是很容易理解錯誤的。
解決從不是建立控制項的執行緒訪問它
在多執行緒程式設計中,我們經常要在工作執行緒中去更新介面顯示,而在多執行緒中直接呼叫介面控制項的方法是錯誤的做法,invoke 和 begininvoke 就是為了解決這個問題而出現的,使你在多執行緒中安全的更新介面顯示。
正確的做法是將工作執行緒中涉及更新介面的**封裝為乙個方法,通過 invoke 或者 begininvoke 去呼叫,兩者的區別就是乙個導致工作執行緒等待,而另外乙個則不會。
而所謂的「一面響應操作,一面新增節點」永遠只能是相對的,使 ui 執行緒的負擔不至於太大而已,因為介面的正確更新始終要通過 ui 執行緒去做,我們要做的事情是在工作執行緒中包攬大部分的運算,而將對純粹的介面更新放到 ui 執行緒中去做,這樣也就達到了減輕 ui 執行緒負擔的目的了。
//啟動乙個執行緒
thread thread=new thread(new threadstart(dowork));
thread.start();
//執行緒方法
private void dowork()
如果你像上面操作,在vs2005或2008裡是會有異常的…
正確的做法是用invoke\begininvoke
using system.threading;
namespace test
public void dowork());}
public void updateform(string param1,string parm2)
private void button1_click(object sender, eventargs e)}}
注意**的使用!
後面再次補充
delegate
void
safesettext
(string strmsg)
;private
void
settext
(string strmsg));
}else
}
delegate
void
safesettext
(string strmsg)
;private
void
settext2
(string strmsg)
textbox1.
invoke
(objset,
newobject
);}
這樣同樣可以實現。
個人覺得還是採用**好些。
在c# 3.0及以後的版本中有了lamda表示式,像上面這種匿名委託有了更簡潔的寫法。.net framework 3.5及以後版本更能用action封裝方法。例如以下寫法可以看上去非常簡潔:
void buttononclick(object sender,eventargs e)
));}
最新:invoke(() =>
);
c Invoke反射簡單舉例
在例子1種必須例項化反射要反射的類,因為要使用的方法並不是靜態方法。建立物件例項 obj ass.createinstance reflectiontest.writetest 執行帶引數的公共方法 method.invoke obj,parametors parametors 異常 必須例項化反射...
C invoke使用方法
在用.net framework框架的winform構建gui程式介面時,如果要在控制項的事件響應函式中改變控制項的狀態,例如 某個按鈕上的文字原先叫 開啟 單擊之後按鈕上的文字顯示 關閉 初學者往往會想當然地這麼寫 void buttononclick object sender,eventarg...
C 學習筆記之invoke與BeginInvoke
invoke與begininvoke的兩種使用情況 1.control中的invoke begininvoke 2.delegrate中的invoke begininvoke 這兩種情況是不同的,這裡主要介紹第一種。dotnet中對invoke和begininvoke的官方定義如下 control....