日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

简单说说async/await

發(fā)布時(shí)間:2023/12/4 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简单说说async/await 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

小明用async/await寫了幾年的異步方法,但總沒(méi)有完全理解里面的機(jī)制,他決定去請(qǐng)教鄰居小花。

小花聽了小明的描述后說(shuō):首先你要明白異步的根本是什么?大白話解釋異步就是:拉一個(gè)人(線程)幫著做一些耗時(shí)的事(下載、讀寫數(shù)據(jù)庫(kù)等),自己先做別的事了(退出線程),等做好了和我說(shuō)下,我再繼續(xù)做后面的事(恢復(fù)上下文)。

小花看到小明還沒(méi)有聽明白,就說(shuō):我舉個(gè)簡(jiǎn)單例子幫你理解吧,假如有兩個(gè)方法A和B,A調(diào)用B方法,B方法是一個(gè)異步方法,這時(shí)A不等待B執(zhí)行完,如圖:

現(xiàn)在兩個(gè)方法被分隔幾個(gè)小塊,await關(guān)鍵字其實(shí)就用來(lái)隔開同步和異步,上面的方法執(zhí)行流程如下:

A調(diào)用B方法后,B方法在未執(zhí)行到await之前還是同步方法,比如輸出Sub1還是在當(dāng)前線程中執(zhí)行,當(dāng)方法遇到await后,就會(huì)把a(bǔ)wait后的方法放到新的線程中執(zhí)行,當(dāng)前線程則退出函數(shù),由于調(diào)用的地方并沒(méi)有await,則主線程會(huì)繼續(xù)執(zhí)行并輸出Part2,然后結(jié)束。等新線程中Thread.Sleep(5000)執(zhí)行完后,會(huì)執(zhí)行到Console.Write("Sub2");這一行代碼會(huì)回到原來(lái)的線程執(zhí)行,其實(shí)調(diào)用線程在遇到await時(shí)會(huì)捕獲當(dāng)前線程的執(zhí)行上下文,然后給到新線程,新線程在執(zhí)行完耗時(shí)操作后,會(huì)判斷之前捕獲到的執(zhí)行上下方是否為null,如果不為null,則會(huì)在上下文中恢復(fù)并執(zhí)行后面的方法,其實(shí)就是通過(guò)Tak的ContineWith方法注冊(cè)回調(diào),如圖:

小明好像聽懂了一些說(shuō):現(xiàn)在A方法調(diào)用DoSomethingAsync()并沒(méi)有等待,如果A方法需要這個(gè)方法執(zhí)行完才能繼續(xù)執(zhí)行,是不是要在DoSomethingAsync()前面加上await?小花回答是,并說(shuō):方法只要遇到await,就會(huì)把后面的方法給新線程執(zhí)行,然后退出線程去執(zhí)行別的方法,等新線程執(zhí)行完后再通知當(dāng)前線程恢復(fù)上下文繼續(xù)執(zhí)行,如圖:

小明又問(wèn):你說(shuō)異步方法執(zhí)行完后,后面的方法會(huì)在原來(lái)的線程中恢復(fù)并執(zhí)行,如果我還想在新線程中繼續(xù)執(zhí)行剩下的代碼,要怎么辦呢?小花說(shuō)問(wèn)的好,await調(diào)用新線程執(zhí)行耗時(shí)操作時(shí)默認(rèn)會(huì)捕獲當(dāng)前上下文,如果不想捕獲,則可以調(diào)用ConfigAwait(false)方法,如圖:

執(zhí)行流程如下:

小花補(bǔ)充到,上線提到的線程1、線程2、線程3等不一定準(zhǔn)確,因?yàn)楫惒降幕卣{(diào)使用的是線程池中的線程,所以回調(diào)有可能還在原來(lái)線程中執(zhí)行,這個(gè)主要看操作系統(tǒng)的調(diào)度。

小明滿意地點(diǎn)點(diǎn)頭又問(wèn):我經(jīng)常聽同事說(shuō)用異步方法會(huì)死鎖,這又是為什么呢?小花聽了說(shuō),他們肯定是在調(diào)用異步方法的時(shí)候使用.Result(),如圖:

小花指著圖解釋說(shuō):上面的代碼task.Result()會(huì)阻塞線程并等待task返回結(jié)果,DoSomethingAsync方法在執(zhí)行完Thread.Sleep(5000)后,發(fā)現(xiàn)捕獲到的上下文不為空,則會(huì)嘗試將Console.Write("Sub2")這行代碼交由調(diào)用線程去執(zhí)行,而這時(shí)調(diào)用線程還在阻塞等待,就這樣互相卡著對(duì)方,從而造成了死鎖,如圖:

小明點(diǎn)了點(diǎn)頭又問(wèn):那要怎么避免呢?小花說(shuō)出現(xiàn)這種情況也和框架有關(guān),像WinForm為了讓所有UI操作都在主線程中執(zhí)行,就添加了一個(gè)SynchronizationContext類實(shí)例用以表示當(dāng)前上下文,而像控制臺(tái)等項(xiàng)目這個(gè)SynchronizationContext實(shí)例默認(rèn)為null,所以即使使用.Result也不會(huì)死鎖。但最好使用異步的時(shí)候不要用.Result,可以使用ConfigAwait(false)指明不捕獲上下文,或所有的方法全部異步到底。

小明聽完,拜別了小花,回到了自己的隔間。

總結(jié)

以上是生活随笔為你收集整理的简单说说async/await的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。