c# Invoke和BeginInvoke 差別剖析。本站提示廣大學習愛好者:(c# Invoke和BeginInvoke 差別剖析)文章只能為提供參考,不一定能成為您想要的結果。以下是c# Invoke和BeginInvoke 差別剖析正文
Control.Invoke 辦法 (Delegate) :在具有此控件的基本窗口句柄的線程上履行指定的拜托。
Control.BeginInvoke 辦法 (Delegate) :在創立控件的基本句柄地點線程上異步履行指定拜托。
(一)Control的Invoke和BeginInvoke
我們要基於以下熟悉:
(1)Control的Invoke和BeginInvoke與Delegate的Invoke和BeginInvoke是分歧的。
(2)Control的Invoke和BeginInvoke的參數為delegate,拜托的辦法是在Control的線程上履行的,也就是我們日常平凡所說的UI線程。
我們以代碼(一)來看(Control的Invoke)
private delegate void InvokeDelegate(); private void InvokeMethod(){ //C代碼段 } private void butInvoke_Click(object sender, EventArgs e) { //A代碼段....... this.Invoke(new InvokeDelegate(InvokeMethod)); //B代碼段...... }
你認為代碼的履行次序是甚麼呢?記好Control的Invoke和BeginInvoke都履行在主線程即UI線程上
A------>C---------------->B
說明:(1)A在UI線程上履行完後,開端Invoke,Invoke是同步
(2)代碼段B其實不履行,而是立刻在UI線程上履行InvokeMethod辦法,即代碼段C。
(3)InvokeMethod辦法履行完後,代碼段C才在UI線程上持續履行。
看看代碼(二),Control的BeginInvoke
private delegate void BeginInvokeDelegate(); private void BeginInvokeMethod(){ //C代碼段 } private void butBeginInvoke_Click(object sender, EventArgs e) { //A代碼段....... this.BeginInvoke(new BeginInvokeDelegate(BeginInvokeMethod)); //B代碼段...... }
你認為代碼的履行次序是甚麼呢?記好Control的Invoke和BeginInvoke都履行在主線程即UI線程上
A----------->B--------------->C鄭重,這個只做參考。。。。。,我也不願定履行次序,假如有哪位達人曉得的話請告訴。
說明::(1)A在UI線程上履行完後,開端BeginInvoke,BeginInvoke是異步
(2)InvokeMethod辦法,即代碼段C不會履行,而是立刻在UI線程上履行代碼段B。
(3)代碼段B履行完後(就是說butBeginInvoke_Click辦法履行完後),InvokeMethod辦法,即代碼段C才在UI線程上持續履行。
由此,我們曉得:
Control的Invoke和BeginInvoke的拜托辦法是在主線程,即UI線程上履行的。也就是說假如你的拜托辦法用來取消費時光長的數據,然後更新界面甚麼的,萬萬別在UI線程上挪用Control.Invoke和Control.BeginInvoke,由於這些是仍然壅塞UI線程的,形成界面的假逝世。
那末,這個異步究竟是甚麼意思呢?
異步是指絕對於挪用BeginInvoke的線程異步,而不是絕對於UI線程異步,你在UI線程上挪用BeginInvoke ,固然不可了。----摘自"Invoke和BeginInvoke的真正涵義"一文中的評論。
BeginInvoke的道理是將挪用的辦法Marshal成新聞,然後挪用Win32 API中的RegisterWindowMessage()向UI窗口發送新聞。----摘自"Invoke和BeginInvoke的真正涵義"一文中的評論。
(二)我們用Thread來挪用BeginInvoke和Invoke
我們開一個線程,讓線程履行一些消耗時光的操作,然後再用Control.Invoke和Control.BeginInvoke回到用戶UI線程,履行界面更新。
代碼(三) Thread挪用Control的Invoke
private Thread invokeThread; private delegate void invokeDelegate(); private void StartMethod(){ //C代碼段...... Control.Invoke(new invokeDelegate(invokeMethod)); //D代碼段...... } private void invokeMethod(){ //E代碼段 } private void butInvoke_Click(object sender, EventArgs e) { //A代碼段....... invokeThread = new Thread(new ThreadStart(StartMethod)); invokeThread.Start(); //B代碼段...... }
你認為代碼的履行次序是甚麼呢?記好Control的Invoke和BeginInvoke都履行在主線程即UI線程上
A------>(Start一開端B和StartMethod的C就同時履行)---->(C履行完了,不論B有無履行完,invokeThread把新聞封送(invoke)給UI線程,然後本身期待)---->UI線程處置完butInvoke_Click新聞後,處置invokeThread封送過去的新聞,履行invokeMethod辦法,即代碼段E,處置往後UI線程切換到invokeThread線程。
這個Control.Invoke是絕對於invokeThread線程同步的,阻攔了其運轉。
說明:
1。UI履行A
2。UI開線程InvokeThread,B和C同時履行,B履行在線程UI上,C履行在線程invokeThread上。
3。invokeThread封送新聞給UI,然後本身期待,UI處置完新聞後,處置invokeThread封送的新聞,即代碼段E
4。UI履行完E後,轉到線程invokeThread上,invokeThread線程履行代碼段D
代碼(四) Thread挪用Control的BeginInvoke
private Thread beginInvokeThread; private delegate void beginInvokeDelegate(); private void StartMethod(){ //C代碼段...... Control.BeginInvoke(new beginInvokeDelegate(beginInvokeMethod)); //D代碼段...... } private void beginInvokeMethod(){ //E代碼段 } private void butBeginInvoke_Click(object sender, EventArgs e) { //A代碼段....... beginInvokeThread = new Thread(new ThreadStart(StartMethod)); beginInvokeThread .Start(); //B代碼段...... }
你認為代碼的履行次序是甚麼呢?記好Control的Invoke和BeginInvoke都履行在主線程即UI線程上
A在UI線程上履行----->beginInvokeThread線程開端履行,UI持續履行代碼段B,並發地invokeThread履行代碼段C-------------->不論UI有無履行完代碼段B,這時候beginInvokeThread線程把新聞封送給UI,單本身其實不期待,持續向下履行-------->UI處置完butBeginInvoke_Click新聞後,處置beginInvokeThread線程封送過去的新聞。
說明:
1。UI履行A
2。UI開線程beginInvokeThread,B和C同時履行,B履行在線程UI上,C履行在線程beginInvokeThread上。
3。beginInvokeThread封送新聞給UI,然後本身持續履行代碼D,UI處置完新聞後,處置invokeThread封送的新聞,即代碼段E
有點疑問:假如UI先履行終了,是否是有能夠過了段時光beginInvokeThread才把新聞封送給UI,然後UI才持續履行封送的新聞E。如圖淺綠的部門。
Control的BeginInvoke是絕對於挪用它的線程,即beginInvokeThread絕對是異步的。
是以,我們可以想到。假如要異步取消耗長時光的數據,好比從數據庫中讀年夜量數據,我們應當這麼做。
(1)假如你想阻攔挪用線程,那末挪用代碼(三),代碼段D刪失落,C改成消耗長時光的操作,由於這個操作是在別的一個線程中做的。代碼段E改成更新界面的辦法。
(2)假如你不想阻攔挪用線程,那末挪用代碼(四),代碼段D刪失落,C改成消耗長時光的操作,由於這個操作是在別的一個線程中做的。代碼段E改成更新界面的辦法。