【转】2.1(译)关于async与await的FAQ
傳送門:異步編程系列目錄……
?????????環(huán)境:VS2012(盡管System.Threading.Tasks在.net4.0就引入,在.net4.5中為其增加了更豐富的API及性能提升,另外關(guān)鍵字”async”和”await”是在C#5.0引入的。vs2010打?Visual Studio Async CTP for VS2010補(bǔ)丁可以引入關(guān)鍵字”async”和”await”的支持,但是得不到.net4.5新增API的支持)
????? (CTP:Community Test Preview 社區(qū)測(cè)試試用版,就是一般的測(cè)試版本)
術(shù)語:
APM???????????異步編程模型,Asynchronous Programming Model
EAP???????????基于事件的異步編程模式,Event-based Asynchronous Pattern
TAP???????????基于任務(wù)的異步編程模式,Task-based Asynchronous Pattern
?????????我常常收到來自開發(fā)人員的一些問題,這些問題主要集中在C#和Visual Basic中的新關(guān)鍵字”async”和”await”。我已經(jīng)將這些問題分類整理,并借此機(jī)會(huì)分享給大家。
?
概念概述
1.?????????從哪能獲得關(guān)于”async”和”await”主題的優(yōu)秀資源?
通常,你能在Visual Studio Async主題中找到很多資源(eg:文章、視頻、博客等等)。2011年10月份的MSDN雜志包含了三篇介紹”async”和”await”主題的優(yōu)秀文章。如果你閱讀,我推薦你閱讀順序依次為:
1)?《通過新的 Visual Studio Async CTP 更輕松地進(jìn)行異步編程》
2)?《通過 Await 暫停和播放》
3)?《了解 Async 和 Await 的成本》
.NET團(tuán)隊(duì)博客同樣也有”async”和”await”主題的優(yōu)秀資源:《Async in .NET4.5:?值得期待》
2.?????????為什么需要編譯器幫助我們完成異步編程?
Anders Hejlsberg’s在2011?微軟Build大會(huì)上花了1個(gè)小時(shí)來幫我們說明為什么編譯器在這里真的有用,視頻:《C#和Visual Basic未來的發(fā)展方向》。簡(jiǎn)而言之,傳統(tǒng)的異步編程模型(APM或EAP)要求你手寫大量代碼(eg:連續(xù)傳遞委托、回調(diào))來實(shí)現(xiàn),并且這些代碼會(huì)導(dǎo)致語句控制流混亂顛倒。通過.NET4.5提供的新的編程模型(TAP),你可以像在寫同步代碼一樣使用常規(guī)的順序控制流結(jié)合并行任務(wù)及”async”和”await”關(guān)鍵字來完成異步編程,編譯器在后臺(tái)應(yīng)用必要的轉(zhuǎn)換以使用回調(diào)方式來避免阻塞線程。
3.?????????通過Task.Run()?將同步方法包裝成異步任務(wù)是否真的有益處?
這取決于你的目標(biāo),你為什么要異步調(diào)用方法。如果你的目標(biāo)只是想將當(dāng)前任務(wù)切換到另一個(gè)線程執(zhí)行,比如,保證UI線程的響應(yīng)能力,那么肯定有益。如果你的目標(biāo)是為了提高可擴(kuò)展性,那么使用Task.Run()?包裝成異步調(diào)用將沒有任何實(shí)際意義。更多信息,請(qǐng)看《我是否應(yīng)該公開同步方法對(duì)應(yīng)的異步方法API?》。通過Task.Run()?你可以很輕松的實(shí)現(xiàn)從UI線程分擔(dān)工作到另一個(gè)工作線程,且可協(xié)調(diào)后臺(tái)線程一旦完成工作就返回到UI線程。(這里說的可擴(kuò)展性就如當(dāng)增加cpu時(shí),Task.Run()并不會(huì)增加程序的并行效率,因?yàn)樗幌喈?dāng)于啟動(dòng)了一個(gè)線程執(zhí)行任務(wù),倘若使用Parallel.For就具有更好的可擴(kuò)展性。什么是系統(tǒng)的可擴(kuò)展性?)
?
“async”關(guān)鍵字
1.?????????將關(guān)鍵字”async”應(yīng)用到方法上的作用是什么?
當(dāng)你用關(guān)鍵字”async”標(biāo)記一個(gè)方法時(shí),即告訴了編譯器兩件事:
1)?????????你告訴編譯器,想在方法內(nèi)部使用”await”關(guān)鍵字(只有標(biāo)記了”async”關(guān)鍵字的方法或lambda表達(dá)式才能使用”await”關(guān)鍵字)。這樣做后,編譯器會(huì)將方法轉(zhuǎn)化為包含狀態(tài)機(jī)的方法(類似的還有yield的工作原理,請(qǐng)看?《C#穩(wěn)固基礎(chǔ):傳統(tǒng)遍歷與迭代器》?),編譯后的方法可以在await處掛起并且在await標(biāo)記的任務(wù)完成后異步喚醒。
2)?????????你告訴編譯器,方法的結(jié)果或任何可能發(fā)生的異常都將作為返回類型返回。如果方法返回Task或Task<TResult>,這意味著任何結(jié)果值或任何在方法內(nèi)部未處理的異常都將存儲(chǔ)在返回的Task中。如果方法返回void,這意味著任何異常會(huì)被傳播到調(diào)用者上下文。
a)?????????async void函數(shù)只能在UI Event回調(diào)中使用。
b)?????????async void函數(shù)中一定要用try-catch捕獲所有異常,否則會(huì)很容易導(dǎo)致程序崩潰。另外需要特別注意lambda表達(dá)式,
如:(List<T>?只有?public void ForEach(Action<T> action);?重載)
| 1 | Enumerable.Range(0, 3).ToList().ForEach(async (i) => { throw?new?Exception(); }); |
這段代碼就隱式生成了async void?函數(shù),直接導(dǎo)致了程序的crash。
?????????不過好在,編譯器是優(yōu)先考慮生成?async Task?形式的匿名函數(shù)的。即如下兩個(gè)重載,編譯器是使用ForEach(Func<T, Task> action);重載生成async Task?函數(shù)。
| 1 2 | public?void?ForEach(Action<T> action); public?void?ForEach(Func<T, Task> action); |
c)?????????注冊(cè)TaskScheduler.UnobservedTaskException事件,記錄Task中未處理異常信息,方便分析及錯(cuò)誤定位。
2.?????????被”async”關(guān)鍵字標(biāo)記的方法的調(diào)用都會(huì)強(qiáng)制轉(zhuǎn)變?yōu)楫惒椒绞絾?#xff1f;
不會(huì),當(dāng)你調(diào)用一個(gè)標(biāo)記了”async”關(guān)鍵字的方法,它會(huì)在當(dāng)前線程以同步的方式開始運(yùn)行。所以,如果你有一個(gè)同步方法,它返回void并且你做的所有改變只是將其標(biāo)記的”async”,這個(gè)方法調(diào)用依然是同步的。返回值為Task或Task<TResult>也一樣。
方法用”async”關(guān)鍵字標(biāo)記不會(huì)影響方法是同步還是異步運(yùn)行并完成,而是,它使方法可被分割成多個(gè)片段,其中一些片段可能異步運(yùn)行,這樣這個(gè)方法可能異步完成。這些片段界限就出現(xiàn)在方法內(nèi)部顯示使用”await”關(guān)鍵字的位置處。所以,如果在標(biāo)記了”async”的方法中沒有顯示使用”await”,那么該方法只有一個(gè)片段,并且將以同步方式運(yùn)行并完成。
3.?????????“async”關(guān)鍵字會(huì)導(dǎo)致調(diào)用方法被排隊(duì)到ThreadPool嗎?會(huì)創(chuàng)建一個(gè)新的線程嗎?
全都不會(huì),”async”關(guān)鍵字指示編譯器在方法內(nèi)部可能會(huì)使用”await”關(guān)鍵字,這樣該方法就可以在await處掛起并且在await標(biāo)記的任務(wù)完成后異步喚醒。這也是為什么編譯器在編譯”async”?標(biāo)記的方法時(shí),方法內(nèi)部沒有使用”await”會(huì)出現(xiàn)警告的原因(warning CS4014:?由于不等待此調(diào)用,因此會(huì)在此調(diào)用完成前繼續(xù)執(zhí)行當(dāng)前方法。請(qǐng)考慮向此調(diào)用的結(jié)果應(yīng)用"await"運(yùn)算符)。
4.?????????”async”關(guān)鍵字能標(biāo)記任何方法嗎?
不能,只有返回類型為void、Task或Task<TResult>的方法才能用”async”標(biāo)記。并且,并不是所有返回類型滿足上面條件的方法都能用”async”標(biāo)記。如下,我們不允許使用”async”標(biāo)記方法:
1)?????????在程序的入口方法(eg:Main()),不允許。當(dāng)你正在await的任務(wù)還未完成,但執(zhí)行已經(jīng)返回給方法的調(diào)用者了。Eg:Main(),這將退出Main(),直接導(dǎo)致退出程序。
2)?????????在方法包含如下特性時(shí),不允許。
l??[MethodImpl(MethodImplOptions.Synchronized)]
為什么這是不允許的,詳細(xì)請(qǐng)看《What’s New for Parallelism in .NET 4.5 Beta》。此特性將方法標(biāo)記為同步類似于使用lock/SyncLock同步基元包裹整個(gè)方法體。
l??[SecurityCritical]和[SecuritySafeCritical]???(Critical:關(guān)鍵)
?????????編譯器在編譯一個(gè)”async”標(biāo)記的方法,原方法體實(shí)際上最終被編譯到新生成的MoveNext()方法中,但是其標(biāo)記的特性依然存在。這意味著特性如[SecurityCritical]不會(huì)正常工作。
3)?????????在包含ref或out參數(shù)的方法中,不允許。調(diào)用者期望方法同步調(diào)用完成時(shí)能確保設(shè)置參數(shù)值,但是標(biāo)記為”async”的方法可能不能保證立刻設(shè)置參數(shù)值直到異步調(diào)用完成。
4)?????????Lambda被用作表達(dá)式樹時(shí),不允許。異步lambda表達(dá)式不能被轉(zhuǎn)換為表達(dá)式樹。
5.?????????是否有任何約定,這時(shí)應(yīng)該使用”async”標(biāo)記方法?
有,基于任務(wù)的異步編程模型(TAP)是完全專注于怎樣實(shí)現(xiàn)異步方法,這個(gè)方法返回Task或Task<TResult>。這包括(但不限于)使用”async”和”await”關(guān)鍵字實(shí)現(xiàn)的方法。想要深入TAP,請(qǐng)看《基于任務(wù)的異步編程模型》文檔。
6.?????????“async”標(biāo)記的方法創(chuàng)建的Tasks是否需要調(diào)用”Start()”?
不需要,TAP方法返回的Tasks是已經(jīng)正在操作的任務(wù)。你不僅不需要調(diào)用”Start()”,而且如果你嘗試也會(huì)失敗。更多細(xì)節(jié),請(qǐng)看《.NET4.X 并行任務(wù)中Task.Start()的FAQ》?。
7.?????????“async”標(biāo)記的方法創(chuàng)建的Tasks是否需要調(diào)用”Dispose()”?
不需要,一般來說,你不需要?Dispose()?任何任務(wù)。請(qǐng)看《.NET4.X并行任務(wù)Task需要釋放嗎?》。
8.?????????“async”是如何關(guān)聯(lián)到當(dāng)前SynchronizationContext?
對(duì)于”async”?標(biāo)記的方法,如果返回Task或Task<TResult>,則沒有方法級(jí)的SynchronizationContext交互;對(duì)于”async”?標(biāo)記的方法,如果返回void,則有一個(gè)隱藏的SynchronizationContext交互。
當(dāng)一個(gè)”async void”方法被調(diào)用,方法調(diào)用的開端將捕獲當(dāng)前SynchronizationContext(“捕獲”在這表示訪問它并且將其存儲(chǔ))。如果這里有一個(gè)非空的SynchronizationContext,將會(huì)影響兩件事:(前提:”async void”)
1)?????????在方法調(diào)用的開始將導(dǎo)致調(diào)用捕獲SynchronizationContext.OperationStarted()方法,并且在完成方法的執(zhí)行時(shí)(無論是同步還是異步)將導(dǎo)致調(diào)用捕獲SynchronizationContext.OprationCompleted()方法。這給上下文引用計(jì)數(shù)未完成異步操作提供時(shí)機(jī)點(diǎn)。如果TAP方法返回Task或Task<TResult>,調(diào)用者可通過返回的Task做到同樣的跟蹤。
2)?????????如果這個(gè)方法是因?yàn)槲刺幚淼漠惓?dǎo)致方法完成,那么這個(gè)異常將會(huì)提交給捕獲的SynchronizationContext。這給上下文一個(gè)處理錯(cuò)誤的時(shí)機(jī)點(diǎn)。如果TAP方法返回Task或Task<TResult>,調(diào)用者可通過返回的Task得到異常信息。
當(dāng)調(diào)用”async void”方法時(shí)如果沒有SynchronizationContext,沒有上下文被捕獲,然后也不會(huì)調(diào)用OperaionStarted/OperationCompleted方法。在這種情況下,如果存在一個(gè)未處理過的異常在ThreadPool上傳播,那么這會(huì)采取線程池線程默認(rèn)行為,即導(dǎo)致進(jìn)程被終止。
?
“await”關(guān)鍵字
1.?????????“await”關(guān)鍵字做了什么
“await”關(guān)鍵字告訴編譯器在”async”標(biāo)記的方法中插入一個(gè)可能的掛起/喚醒點(diǎn)。
?????????邏輯上,這意味著當(dāng)你寫”await someObject;”時(shí),編譯器將生成代碼來檢查someObject代表的操作是否已經(jīng)完成。如果已經(jīng)完成,則從await標(biāo)記的喚醒點(diǎn)處繼續(xù)開始同步執(zhí)行;如果沒有完成,將為等待的someObject生成一個(gè)continue委托,當(dāng)someObject代表的操作完成的時(shí)候調(diào)用continue委托。這個(gè)continue委托將控制權(quán)重新返回到”async”方法對(duì)應(yīng)的await喚醒點(diǎn)處。
返回到await喚醒點(diǎn)處后,不管等待的someObject是否已經(jīng)經(jīng)完成,任何結(jié)果都可從Task中提取,或者如果someObject操作失敗,發(fā)生的任何異常隨Task一起返回或返回給SynchronizationContext。
?????????在代碼中,意味著當(dāng)你寫:
???????? await someObject;
?????????編譯器會(huì)生成一個(gè)包含 MoveNext 方法的狀態(tài)機(jī)類:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | private?class?FooAsyncStateMachine : IAsyncStateMachine { ????// Member fields for preserving “l(fā)ocals” and other necessary???? state ????int?$state; ????TaskAwaiter $awaiter; ????… ????public?void?MoveNext() ????{ ????????// Jump table to get back to the right statement upon???????? resumption ????????switch?(this.$state) ????????{ ????????????… ????????case?2: goto?Label2; ????????????… ????????} ????????… ????????// Expansion of “await someObject;” ????????this.$awaiter = someObject.GetAwaiter(); ????????if?(!this.$awaiter.IsCompleted) ????????{ ????????????this.$state = 2; ????????????this.$awaiter.OnCompleted(MoveNext); ????????????return; ????????????Label2: ????????} ????????this.$awaiter.GetResult(); ????????… ????} } |
在實(shí)例?someObject上使用這些成員來檢查該對(duì)象是否已完成(通過?IsCompleted),如果未完成,則掛接一個(gè)續(xù)體(通過?OnCompleted),當(dāng)所等待實(shí)例最終完成時(shí),系統(tǒng)將再次調(diào)用?MoveNext?方法,完成后,來自該操作的任何異常將得到傳播或作為結(jié)果返回(通過?GetResult),并跳轉(zhuǎn)至上次執(zhí)行中斷的位置。
2.?????????什么是”awaitables”?什么是”awaiters”?
?????????雖然Task和Task<TResult>是兩個(gè)非常普遍的等待類型(“awaitable”),但這并不表示只有這兩個(gè)的等待類型。
“awaitable”可以是任何類型,它必須公開一個(gè)GetAwaiter()?方法并且返回有效的”awaiter”。這個(gè)GetAwaiter()?可能是一個(gè)實(shí)例方法(eg:Task或Task<TResult>的實(shí)例方法),或者可能是一個(gè)擴(kuò)展方法。
“awaiter”是”awaitable”對(duì)象的GetAwaiter()方法返回的符合特定的模式的類型?!盿waiter”必須實(shí)現(xiàn)System.Runtime.CompilerServices.INotifyCompletion接口(,并可選的實(shí)現(xiàn)System.Runtime.CompilerServices.ICriticalNotifyCompletion接口)。除了提供一個(gè)INotifyCompletion接口的OnCompleted方法實(shí)現(xiàn)(,可選提供ICriticalNotifyCompletion接口的UnsafeCompleted方法實(shí)現(xiàn)),還必須提供一個(gè)名為IsCompleted的Boolean屬性以及一個(gè)無參的GetResult()方法。GetResult()返回void,如果”awaitable”代表一個(gè)void返回操作,或者它返回一個(gè)TResult,如果”awaitable”代表一個(gè)TResult返回操作。
幾種方法來實(shí)現(xiàn)自定義的”awaitable”?談?wù)?#xff0c;請(qǐng)看《await anything》。也能針對(duì)特殊的情景實(shí)現(xiàn)自定義”awaitable”,請(qǐng)看《Advanced APM Consumption in Async Methods》和《Awaiting Socket Operations》。
3.?????????哪些地方不能使用”await”?
1)?????????在未標(biāo)記”async”的方法或lambda表達(dá)式中,不能使用”await”。”async”關(guān)鍵字告訴編譯器其標(biāo)記的方法內(nèi)部可以使用”await”。(更詳細(xì),請(qǐng)看《Asynchrony in C# 5 Part Six: Whither async?》)
2)?????????在屬性的getter或setter訪問器中,不能使用”await”。屬性的意義是快速的返回給調(diào)用者,因此不期望使用異步,異步是專門為潛在的長時(shí)間運(yùn)作的操作。如果你必須在你的屬性中使用異步,你可以通過實(shí)現(xiàn)異步方法然后在你的屬性中調(diào)用。
3)?????????在lock/SyncLock塊中,不能使用”await”。關(guān)于談?wù)摓槭裁床辉试S,以及SemaphoreSlim.WaitAsync(哪一個(gè)能用于此情況的等待),請(qǐng)看《What’s New for Parallelism in .NET 4.5 Beta》。你還可以閱讀如下文章,關(guān)于如何構(gòu)建各種自定義異步同步基元:
a)?????????構(gòu)建Async同步基元,Part 1 AsyncManualResetEvent
b)?????????構(gòu)建Async同步基元,Part 2 AsyncAutoResetEvent
c)?????????構(gòu)建Async同步基元,Part 3 AsyncCountdownEvent
d)?????????構(gòu)建Async同步基元,Part 4 AsyncBarrier
e)?????????構(gòu)建Async同步基元,Part 5 AsyncSemaphore
f)??????????構(gòu)建Async同步基元,Part 6 AsyncLock
g)?????????構(gòu)建Async同步基元,Part 7 AsyncReaderWriterLock
4)?????????在unsafe區(qū)域中,不能使用”await”。注意,你能在標(biāo)記”async”的方法內(nèi)部使用”unsafe”關(guān)鍵字,但是你不能在unsafe區(qū)域中使用”await”。
5)?????????在catch塊和finally塊中,不能使用”await”。你能在try塊中使用”await”,不管它是否有相關(guān)的catch塊和finally塊,但是你不能在catch塊或finally塊中使用”await”。這樣做會(huì)破壞CLR的異常處理。
6)?????????LINQ中大部分查詢語法中,不能使用”await”?!盿wait”可能只用于查詢表達(dá)式中的第一個(gè)集合表達(dá)式的”from”子句或在集合表達(dá)式中的”join”子句。
4.?????????“await task;”和”task.Wait”效果一樣嗎?
不。
“task.Wait()”是一個(gè)同步,可能阻塞的調(diào)用。它不會(huì)立刻返回到Wait()的調(diào)用者,直到這個(gè)任務(wù)進(jìn)入最終狀態(tài),這意味著已進(jìn)入RanToCompletion,Faulted,或Canceled完成狀態(tài)。相比之下,”await task;”告訴編譯器在”async”標(biāo)記的方法內(nèi)部插入一個(gè)隱藏的掛起/喚醒點(diǎn),這樣,如果等待的task沒有完成,異步方法也會(huì)立馬返回給調(diào)用者,當(dāng)?shù)却娜蝿?wù)完成時(shí)喚醒它從隱藏點(diǎn)處繼續(xù)執(zhí)行。當(dāng)”await task;”會(huì)導(dǎo)致比較多應(yīng)用程序無響應(yīng)或死鎖的情況下使用“task.Wait()”。更多信息請(qǐng)看《Await, and UI, and deadlocks! Oh my!》。
???????????????????當(dāng)你使用”async”和”await”時(shí),還有其他一些潛在缺陷。Eg:
1)?????????避免傳遞lambda表達(dá)式的潛在缺陷
2)?????????保證”async”方法不要被釋放
3)?????????不要忘記完成你的任務(wù)
4)?????????使用”await”依然可能存在死鎖?
5.?????????“task.Result”與”task.GetAwaiter().GetResult()”之間存在功能區(qū)別嗎?
存在。但僅僅在任務(wù)以非成功狀態(tài)完成的情況下。如果task是以RanToCompletion狀態(tài)完成,那么這兩個(gè)語句是等價(jià)的。然而,如果task是以Faulted或Canceled狀態(tài)完成,task.Result將傳播一個(gè)或多個(gè)異常封裝而成的AggregateException對(duì)象;而”task.GetAwaiter().GetResult()”將直接傳播異常(如果有多個(gè)任務(wù),它只會(huì)傳播其中一個(gè))。關(guān)于為什么會(huì)存在這個(gè)差異,請(qǐng)看《.NET4.5中任務(wù)的異常處理》。
6.?????????“await”是如何關(guān)聯(lián)到當(dāng)前SynchronizationContext?
這完全取決于被等待的類型。對(duì)于給定的”awaitable”,編譯器生成的代碼最終會(huì)調(diào)用”awaiter”的OnCompleted()方法,并且傳遞將執(zhí)行的continue委托。編譯器生成的代碼對(duì)SynchronizationContext一無所知,僅僅依賴當(dāng)?shù)却牟僮魍瓿蓵r(shí)調(diào)用OnCompleted()方法時(shí)所提供的委托。這就是OnCompleted()方法,它負(fù)責(zé)確保委托在”正確的地方”被調(diào)用,”正確的地方”完全由”awaiter”決定。
正在等待的任務(wù)(由Task和Task<TResult>的GetAwaiter方法分別返回的TaskAwaiter和TaskAwaiter<TResult>類型)的默認(rèn)行為是在掛起前捕獲當(dāng)前的SynchronizationContext,然后等待task的完成,如果能捕獲到當(dāng)前的SynchronzationContext,調(diào)用continue委托將控制權(quán)返回到SynchronizationContext中。所以,例如,如果你在應(yīng)用程序的UI線程上執(zhí)行”await task;”,如果當(dāng)前SynchronizationContext非空則將調(diào)用OnCompleted(),并且在任務(wù)完成時(shí),將使用UI的SynchronizationContext傳播continue委托返回到UI線程。
當(dāng)你等待一個(gè)任務(wù),如果沒有當(dāng)前SynchronizationContext,那么系統(tǒng)會(huì)檢查當(dāng)前的TaskScheduler,如果有,當(dāng)task完成時(shí)將使用TaskScheduler調(diào)度continue委托。
如果SynchronizationContext和TaskScheduler都沒有,無法迫使continue委托返回到原來的上下文,或者你使用”await task.ConfigureAwait(false)代替”await task;”,然后continue委托不會(huì)迫使返回到原來上下文并且將允許在系統(tǒng)認(rèn)為合適的地方繼續(xù)運(yùn)行。這通常意味著要么以同步方式運(yùn)行continue委托,無論等待的task在哪完成;要么使用ThreadPool中的線程運(yùn)行continue委托。
7.?????????在控制臺(tái)程序中能使用”await”嗎?
當(dāng)然能。但你不能在Main()方法中使用”await”,因?yàn)槿肟邳c(diǎn)不能被標(biāo)記為”async”。相反,你能在控制臺(tái)應(yīng)用程序的其他方法中使用”await”。如果你在Main()中調(diào)用這些方法,你可以同步等待(而不是異步等待)他們的完成。Eg:
?????????你還可以使用自定義的SynchronizationContext或TaskScheduler來實(shí)現(xiàn)相似的功能,更多信息請(qǐng)看:
1)?????????Await, SynchronizationContext, and Console Apps: Part 1
2)?????????Await, SynchronizationContext, and Console Apps: Part 2
3)?????????Await, SynchronizationContext, and Console Apps: Part 3
8.?????????“await”能和異步編程模型模式(APM)或基于事件的異步編程模式(EAP)一起使用嗎?
當(dāng)然能,你可以為你的異步操作實(shí)現(xiàn)一個(gè)自定義的”awaitable”,或者將你現(xiàn)有的異步操作轉(zhuǎn)化為現(xiàn)有的”awaitable”,像task或task<TResult>。示例如下:
1)?????????Tasks and the APM Pattern
2)?????????Tasks and the Event-based Asynchronous Pattern
3)?????????Advanced APM Consumption in Async Methods
4)?????????Implementing a SynchronizationContext.SendAsync method
5)?????????Awaiting Socket Operations
6)?????????await anything
7)?????????The Nature of TaskCompletionSource<TResult>
9.?????????編譯器對(duì)async/await生成的代碼是否能高效異步執(zhí)行?
大多數(shù)情況下,是的。因?yàn)榇罅康纳纱a已經(jīng)被編譯器所優(yōu)化并且.NET Framework也為生成代碼建立依賴關(guān)系。要了解更多信息,包括使用async/await的最小化開銷的最佳實(shí)踐等。請(qǐng)看
1)?????????.NET4.5對(duì)TPL的性能提升
2)?????????2012年MVP峰會(huì)上的“The Zen of Async”
3)?????????《了解 Async 和 Await 的成本》
?
?
原文:http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx
作者:Stephen Toub - MSFT
另外,稍作改動(dòng),參考文獻(xiàn):C# Async Tips and Tricks Part 2 : Async Void
?
總結(jié)
以上是生活随笔為你收集整理的【转】2.1(译)关于async与await的FAQ的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多家电商平台下架!上外男生给女生投放的牛
- 下一篇: 德普与海后庭审笔记被拍卖:这画面让网友笑