C invoke和begininvoke 的區別

2021-10-06 00:17:31 字數 3518 閱讀 5455

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....