2012-01-07 70 views
74

是否有人可以請客氣一點,以確認我是否已正確理解Async await關鍵字? (使用CTP的版本3)Async是否等待關鍵字等同於ContinueWith lambda?

到目前爲止,我已經計算出,在方法調用之前插入await關鍵字本質上做了2件事情,它創建了一個立即返回值和B.它創建了一個「continuation」在異步方法調用完成時調用。在任何情況下,延續都是該方法的代碼塊的其餘部分。

所以我想知道的是,這兩個代碼在技術上是否等價,如果是這樣,這是否基本上意味着await關鍵字與創建ContinueWith Lambda相同(即:它基本上是一個編譯器快捷方式) ?如果不是,有什麼區別?

bool Success = 
    await new POP3Connector(
     "mail.server.com", txtUsername.Text, txtPassword.Text).Connect(); 
// At this point the method will return and following code will 
// only be invoked when the operation is complete(?) 
MessageBox.Show(Success ? "Logged In" : "Wrong password"); 

VS

(new POP3Connector(
    "mail.server.com", txtUsername.Text, txtPassword.Text).Connect()) 
.ContinueWith((success) => 
    MessageBox.Show(success.Result ? "Logged In" : "Wrong password")); 

回答

73

的總體思路是正確的 - 該方法的其餘部分被製作成各種各樣的延續。

"fast path" blog post詳細說明了編譯器轉換是如何工作的。

差異,把我的頭頂部:

await關鍵字還使用「調度環境」的概念。如果它存在,則調度上下文爲SynchronizationContext.Current,在TaskScheduler.Current上回退。然後繼續在調度上下文中運行。因此,如果需要,更近似的方法是將TaskScheduler.FromCurrentSynchronizationContext轉換爲ContinueWith,如果有必要的話,則可以使用TaskScheduler.Current

實際的async/await實現基於模式匹配;它使用「等待」模式,允許等待除了任務之外的其他事情。一些例子是WinRT異步API,一些特殊的方法,如Yield,Rx observables和special socket awaitables that don't hit the GC as hard。任務是強大的,但他們不是唯一的候選人。想到另外一個小小的挑剔的區別:如果awaitable已經完成,那麼async方法實際上並不會在那個時候返回;它繼續同步。所以這就像傳遞TaskContinuationOptions.ExecuteSynchronously,但沒有堆棧相關的問題。

+2

非常好說 - 我試着順從Jon的帖子,因爲它們比我有時間在SO上回答的任何東西都要廣泛得多,但是Stephen的說法絕對正確。 WRT什麼是等待(特別是GetAwaiter),他的帖子#3是非常有用的IMHO :) http://msmvps.com/blogs/jon_skeet/archive/2011/05/13/eduasync-part-3-the-shape- of-the-async-method-awaitable-boundary.aspx – 2012-01-07 16:06:37

+4

Stephen在這裏。對於簡單的例子,很容易認爲異步/等待僅僅是ContinueWith的一個快捷方式 - 但是,我想反過來思考它。異步/等待實際上是您用來使用ContinueWith for的更強大的表達。問題是ContinueWith(...)使用lambda表達式,並允許執行轉移到繼續,但是如果必須將一半的循環體放在ContinueWith(..)之前,其他控制流概念(如循環)是不可能的。 )和另一半之後。您最終會手動繼續鏈接。 – 2012-01-07 21:19:52

+7

另一個異步/等待比ContinueWith(...)更具表現力的例子是異常情況。您可以在同一個try塊中多次等待,並且對於每個執行階段,它們的異常可以集中到相同的catch(...)塊,而無需編寫大量明確執行的代碼。 – 2012-01-07 21:21:07

8

它的 「本質」 是的,但生成的代碼不嚴格的不僅僅是這些。對於許多對生成的代碼更詳細,我會強烈建議喬恩斯基特的Eduasync系列:

http://codeblog.jonskeet.uk/category/eduasync/

尤其是後#7進入被生成的內容(如CTP 2)爲什麼呢,所以大概爲你在此刻找什麼十分契合:

http://codeblog.jonskeet.uk/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method/

編輯:我認爲這是可能比更詳細你從問題中尋找,但如果你想知道什麼當你在方法中有多個等待時,看起來像什麼東西,這是後#9 :)

http://codeblog.jonskeet.uk/2011/05/30/eduasync-part-9-generated-code-for-multiple-awaits/