国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > C# > 正文

c# Invoke和BeginInvoke 區(qū)別分析

2020-01-24 02:20:25
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

Control.Invoke 方法 (Delegate) :擁有此控件的基礎(chǔ)窗口句柄的線程上執(zhí)行指定的委托。

Control.BeginInvoke 方法 (Delegate) :在創(chuàng)建控件的基礎(chǔ)句柄所在線程上異步執(zhí)行指定委托。

(一)Control的Invoke和BeginInvoke

我們要基于以下認(rèn)識(shí):
(1)Control的Invoke和BeginInvoke與Delegate的Invoke和BeginInvoke是不同的。
(2)Control的Invoke和BeginInvoke的參數(shù)為delegate,委托的方法是在Control的線程上執(zhí)行的,也就是我們平時(shí)所說(shuō)的UI線程。

我們以代碼(一)來(lái)看(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代碼段......}

你覺(jué)得代碼的執(zhí)行順序是什么呢?記好Control的Invoke和BeginInvoke都執(zhí)行在主線程即UI線程上
A------>C---------------->B
解釋:(1)A在UI線程上執(zhí)行完后,開(kāi)始Invoke,Invoke是同步
(2)代碼段B并不執(zhí)行,而是立即在UI線程上執(zhí)行InvokeMethod方法,即代碼段C。
(3)InvokeMethod方法執(zhí)行完后,代碼段C才在UI線程上繼續(xù)執(zhí)行。

看看代碼(二),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代碼段......}

你覺(jué)得代碼的執(zhí)行順序是什么呢?記好Control的Invoke和BeginInvoke都執(zhí)行在主線程即UI線程上
A----------->B--------------->C慎重,這個(gè)只做參考。。。。。,我也不肯定執(zhí)行順序,如果有哪位達(dá)人知道的話請(qǐng)告知。

解釋::(1)A在UI線程上執(zhí)行完后,開(kāi)始BeginInvoke,BeginInvoke是異步

(2)InvokeMethod方法,即代碼段C不會(huì)執(zhí)行,而是立即在UI線程上執(zhí)行代碼段B。
(3)代碼段B執(zhí)行完后(就是說(shuō)butBeginInvoke_Click方法執(zhí)行完后),InvokeMethod方法,即代碼段C才在UI線程上繼續(xù)執(zhí)行。

由此,我們知道:

Control的Invoke和BeginInvoke的委托方法是在主線程,即UI線程上執(zhí)行的。也就是說(shuō)如果你的委托方法用來(lái)取花費(fèi)時(shí)間長(zhǎng)的數(shù)據(jù),然后更新界面什么的,千萬(wàn)別在UI線程上調(diào)用Control.Invoke和Control.BeginInvoke,因?yàn)檫@些是依然阻塞UI線程的,造成界面的假死。

那么,這個(gè)異步到底是什么意思呢?

異步是指相對(duì)于調(diào)用BeginInvoke的線程異步,而不是相對(duì)于UI線程異步,你在UI線程上調(diào)用BeginInvoke ,當(dāng)然不行了。----摘自"Invoke和BeginInvoke的真正涵義"一文中的評(píng)論。
BeginInvoke的原理是將調(diào)用的方法Marshal成消息,然后調(diào)用Win32 API中的RegisterWindowMessage()向UI窗口發(fā)送消息。----摘自"Invoke和BeginInvoke的真正涵義"一文中的評(píng)論。

(二)我們用Thread來(lái)調(diào)用BeginInvoke和Invoke

我們開(kāi)一個(gè)線程,讓線程執(zhí)行一些耗費(fèi)時(shí)間的操作,然后再用Control.Invoke和Control.BeginInvoke回到用戶UI線程,執(zhí)行界面更新。

代碼(三) Thread調(diào)用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代碼段......}


你覺(jué)得代碼的執(zhí)行順序是什么呢?記好Control的Invoke和BeginInvoke都執(zhí)行在主線程即UI線程上
A------>(Start一開(kāi)始B和StartMethod的C就同時(shí)執(zhí)行)---->(C執(zhí)行完了,不管B有沒(méi)有執(zhí)行完,invokeThread把消息封送(invoke)給UI線程,然后自己等待)---->UI線程處理完butInvoke_Click消息后,處理invokeThread封送過(guò)來(lái)的消息,執(zhí)行invokeMethod方法,即代碼段E,處理往后UI線程切換到invokeThread線程。

這個(gè)Control.Invoke是相對(duì)于invokeThread線程同步的,阻止了其運(yùn)行。


解釋:

1。UI執(zhí)行A
2。UI開(kāi)線程InvokeThread,B和C同時(shí)執(zhí)行,B執(zhí)行在線程UI上,C執(zhí)行在線程invokeThread上。
3。invokeThread封送消息給UI,然后自己等待,UI處理完消息后,處理invokeThread封送的消息,即代碼段E
4。UI執(zhí)行完E后,轉(zhuǎn)到線程invokeThread上,invokeThread線程執(zhí)行代碼段D

代碼(四) Thread調(diào)用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代碼段......}


你覺(jué)得代碼的執(zhí)行順序是什么呢?記好Control的Invoke和BeginInvoke都執(zhí)行在主線程即UI線程上
A在UI線程上執(zhí)行----->beginInvokeThread線程開(kāi)始執(zhí)行,UI繼續(xù)執(zhí)行代碼段B,并發(fā)地invokeThread執(zhí)行代碼段C-------------->不管UI有沒(méi)有執(zhí)行完代碼段B,這時(shí)beginInvokeThread線程把消息封送給UI,單自己并不等待,繼續(xù)向下執(zhí)行-------->UI處理完butBeginInvoke_Click消息后,處理beginInvokeThread線程封送過(guò)來(lái)的消息。



解釋:

1。UI執(zhí)行A
2。UI開(kāi)線程beginInvokeThread,B和C同時(shí)執(zhí)行,B執(zhí)行在線程UI上,C執(zhí)行在線程beginInvokeThread上。
3。beginInvokeThread封送消息給UI,然后自己繼續(xù)執(zhí)行代碼D,UI處理完消息后,處理invokeThread封送的消息,即代碼段E
有點(diǎn)疑問(wèn):如果UI先執(zhí)行完畢,是不是有可能過(guò)了段時(shí)間beginInvokeThread才把消息封送給UI,然后UI才繼續(xù)執(zhí)行封送的消息E。如圖淺綠的部分。

Control的BeginInvoke是相對(duì)于調(diào)用它的線程,即beginInvokeThread相對(duì)是異步的。
因此,我們可以想到。如果要異步取耗費(fèi)長(zhǎng)時(shí)間的數(shù)據(jù),比如從數(shù)據(jù)庫(kù)中讀大量數(shù)據(jù),我們應(yīng)該這么做。
(1)如果你想阻止調(diào)用線程,那么調(diào)用代碼(三),代碼段D刪掉,C改為耗費(fèi)長(zhǎng)時(shí)間的操作,因?yàn)檫@個(gè)操作是在另外一個(gè)線程中做的。代碼段E改為更新界面的方法。
(2)如果你不想阻止調(diào)用線程,那么調(diào)用代碼(四),代碼段D刪掉,C改為耗費(fèi)長(zhǎng)時(shí)間的操作,因?yàn)檫@個(gè)操作是在另外一個(gè)線程中做的。代碼段E改為更新界面的方法。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 顺昌县| 松溪县| 阿坝| 鹤岗市| 宁武县| 普格县| 卓资县| 孟村| 获嘉县| 彰化县| 阿鲁科尔沁旗| 汕头市| 土默特右旗| 怀宁县| 株洲县| 隆回县| 新蔡县| 泌阳县| 前郭尔| 丽江市| 义马市| 正蓝旗| 武汉市| 连南| 吕梁市| 长兴县| 九江县| 泸溪县| 楚雄市| 澎湖县| 砚山县| 郸城县| 木兰县| 宁都县| 深州市| 永仁县| 罗平县| 伊吾县| 兴城市| 缙云县| 兴国县|