C 中Invoke的用法()

2022-07-02 17:12:08 字數 3368 閱讀 6902

一直對invoke和begininvoke的使用和概念比較混亂,這兩天看了些資料,對這兩個的用法和原理有了些新的認識和理解。

首先說下,invoke和begininvoke的使用有兩種情況:

1. control中的invoke、begininvoke。

2. delegrate中的invoke、begininvoke。  

這兩種情況是不同的,我們這裡要講的是第1種。下面我們在來說下.net中對invoke和begininvoke的官方定義。

control.invoke(引數delegate)方法:在擁有此控制項的基礎視窗控制代碼的執行緒上執行指定的委託。

根據這兩個概念我們大致理解invoke表是同步、begininvoke表示非同步

如果你的後台執行緒在更新乙個ui控制項的狀態後不需要等待,而是要繼續往下處理,那麼你就應該使用begininvoke來進行非同步處理。

如果你的後台執行緒需要操作ui控制項,並且需要等到該操作執行完畢才能繼續執行,那麼你就應該使用invoke。

我們來做乙個測試。

invoke例子:

private void button1_click(objectsender, eventargs e)

messagebox.show(thread.currentthread.gethashcode().tostring()+a);

} private voidstartmethod()

private voidinvokemethod()

結論:我們執行後,看下程式的執行順序,1aaa->3ccc和1bbb->1eee ->3ddd 。 

解釋:主線程執行1aaa,然後1bbb和子執行緒3ccc同時執行,然後通過invoke來將invokemethod方法提交給主線程,然後子線 程等待主線程執行,直到主線程將invokemethod方法執行完成(期間必須等待主線程的任務執行完成,才會去執行invoke提交的任務),最後執 行子執行緒3ddd。

begininvoke例子:

private void button1_click(objectsender, eventargs e)

messagebox.show(thread.currentthread.gethashcode().tostring()+a);

} private voidstartmethod()

private voidbegininvokemethod()

結論: 我們執行後看看執行的結果: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

去呼叫,兩者的區別就是乙個導致工作執行緒等待,而另外乙個則不會。

而所謂的「一面響應操作,一面新增節點」永遠只能是相對的,使 ui 執行緒的負擔不至於太大而已,因為介面的正確更新始終要通過 ui

執行緒去做,我們要做的事情是在工作執行緒中包攬大部分的運算,而將對純粹的介面更新放到 ui 執行緒中去做,這樣也就達到了減輕 ui

using system.threading; 

//啟動乙個執行緒 

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

注意**的使用!

在 定會報出:從不是建立控制項的執行緒訪問它,這個異常。通常我們可以採用兩種方法來解決。一是通過設定control的屬性。二是通過delegate,而通

過delegate也有兩種方式,一種是常用的方式,另一種就是匿名方式。下面分別加以說明.

其次,通過delegate的方法來解決。

普通的委託方法例如:

delegate void safesettext(stringstrmsg);

private void settext(stringstrmsg)

); }

else

}

delegate void safesettext(stringstrmsg);

private void settext2(stringstrmsg)

textbox1.invoke(objset,new object);

}

這樣同樣可以實現。

個人覺得還是採用**好些。

在c# 3.0及以後的版本中有了lamda表示式,像上面這種匿名委託有了更簡潔的寫法。.net framework 3.5及以後版本更能用action封裝方法。例如以下寫法可以看上去非常簡潔:

void buttononclick(object sender,eventargs e)

this.invoke(new action(()=>

button.text="關閉";

最新:invoke(() =>

);

C 中Invoke的用法

在多執行緒程式設計中,我們經常要在工作執行緒中去更新介面顯示,而在多執行緒中直接呼叫介面控制項的方法是錯誤的做法,invoke 和 begininvoke 就是為了解決這個問題而出現的,使你在多執行緒中安全的更新介面顯示。正確的做法是將工作執行緒中涉及更新介面的 封裝為乙個方法,通過 invoke ...

C 中Invoke的用法

在用.net framework框架的winform構建gui程式介面時,如果要在控制項的事件響應函式中改變控制項的狀態,例如 某個按鈕上的文字原先叫 開啟 單擊之後按鈕上的文字顯示 關閉 初學者往往會想當然地這麼寫 void buttononclick object sender,eventarg...

C 中Invoke的用法()

一直對invoke和begininvoke的使用和概念比較混亂,這兩天看了些資料,對這兩個的用法和原理有了些新的認識和理解。首先說下,invoke和begininvoke的使用有兩種情況 1.control中的invoke begininvoke。2.delegrate中的invoke begini...