一直對invoke和begininvoke的使用和概念比較混亂,這兩天看了些資料,對這兩個的用法和原理有了些新的認識和理解。
首先說下,invoke和begininvoke的使用有兩種情況:
1. control中的invoke、begininvoke。
2. delegrate中的invoke、begininvoke。
這兩種情況是不同的,我們這裡要講的是第1種。下面我們在來說下.net中對invoke和begininvoke的官方定義。
control.invoke(引數delegate)方法:在擁有此控制項的基礎視窗控制代碼的執行緒上執行指定的委託。
根據這兩個概念我們大致理解invoke表是同步、begininvoke表示非同步。但是如何來進行同步和非同步呢?我們來做乙個測試。
invoke例子:
private結論:我們執行後,看下程式的執行順序,1aaa->3ccc和1bbb->1eee ->3ddd 。void button1_click(object
sender, eventargs e)
messagebox.show(thread.currentthread.gethashcode().tostring()+a);}
private
void
startmethod()
private
void
invokemethod()
解釋:主線程執行1aaa,然後1bbb和子執行緒3ccc同時執行,然後通過invoke來將invokemethod方法提交給主線程,然後子線 程等待主線程執行,直到主線程將invokemethod方法執行完成(期間必須等待主線程的任務執行完成,才會去執行invoke提交的任務),最後執 行子執行緒3ddd。
begininvoke例子:
private結論: 我們執行後看看執行的結果:1aaa->1bbb和3ccc->1eee和3ddd。void button1_click(object
sender, eventargs e)
messagebox.show(thread.currentthread.gethashcode().tostring()+a);}
private
void
startmethod()
private
void
begininvokemethod()
解釋: 主線程執行1aaa,然後1bbb和子執行緒3ccc同時執行,然後通過begininvoke來將invokemethod方法提交給主線程,然後主線程執行1eee(主線程自己的任務執行完成), 同時子執行緒繼續執行3ddd。
通過這個兩段**的測試比較,我們會發現其實invoke和begininvoke所提交的委託方法都是在主線程中執行的,其實根據我invoke 和begininvoke的定義我們要在子執行緒中來看這個問題,在invoke例子中我們會發現invoke所提交的委託方法執行完成後,才能繼續執行 ddd;在begininvoke例子中我們會發現begininvoke所提交的委託方法後,子執行緒講繼續執行ddd,不需要等待委託方法的完成。 那麼現在我們在回想下invoke(同步)和begininvoke(非同步)的概念,其實它們所說的意思是相對於子執行緒而言的,其實對於控制項的呼叫總是由 主線程來執行的。我們很多人搞不清這個同步和非同步,主要還是因為我們把參照物選錯了。其實有時候光看概念是很容易理解錯誤的。
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)
}
}
注意**的使用!
其次,通過delegate的方法來解決。
普通的委託方法例如:
delegatevoid 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)
this.invoke(new action(()=>
button.text="關閉";
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...