2013-06-29 75 views
8

所以我問this questionasync,我認爲它它只是一個語法糖:c#5異步糖語法(或不)?

Task<..>...ContinueWith...

最後檢查Result財產。

我連問了一個問題關於它here,我被告知:

enter image description here

enter image description here

但今天I was corrected by Jon Skeet

「這是從很遠的路。」

那麼這兩種方法的核心區別是什麼?

+3

*從概念上講* await的使用與ContinueWith類似,但是有很多小的細節會在await中爲你處理,你必須使用ContinueWith來完成自己。 –

+0

你是如何優雅的回答這個問題的? :) –

+0

@YairNevet哪一個? –

回答

15

增加了一個延續 - 但由於需要攜帶所有關於我們到達的地方以及本地狀態是什麼的所有信息,但手動構建延續可能非常痛苦。

作爲非常簡單的例子,我建議你儘量想出這個異步方法相當於:

public static async Task<int> SumTwoOperationsAsync() 
{ 
    var firstTask = GetOperationOneAsync(); 
    var secondTask = GetOperationTwoAsync(); 
    return await firstTask + await secondTask; 
} 

// These are just examples - you don't need to translate them. 
private async Task<int> GetOperationOneAsync() 
{ 
    await Task.Delay(500); // Just to simulate an operation taking time 
    return 10; 
} 

private async Task<int> GetOperationTwoAsync() 
{ 
    await Task.Delay(100); // Just to simulate an operation taking time 
    return 5; 
} 

真正嘗試拿出第一個方法是等效的。我想你會發現它需要相當多的代碼 - ,尤其是,如果你真的想每次都回到適當的線程。 (想象一下,代碼中的異步方法也修改了WPF UI)。哦,並確保如果任一任務失敗,返回的任務也會失敗。 (如果第一個任務也失敗,那麼異步方法實際上會「錯過」第二個任務的失敗,但這是IMO的一個相對較小的問題。)

接下來,研究如果您需要更改代碼在async方法中需要相當於try/finally。再次,這將使非異步方法更復雜。這一切都可以完成,但這是一個痛苦的脖子。

所以是的,它只是「語法糖」。所以是foreach。所以是一個for循環(或任何其他類型的循環)。在async/await的情況下,它是一種語法糖,它對於轉換代碼確實可以做很多事情。

很多周圍異步視頻和博客文章,我會期望只是看着/讀取其中的幾個會給你足夠的洞察力,認識到這遠非一個小調整:它根本改變了正確編寫大量異步代碼的實用性。

此外,基於圖案,異步/等待不只有工作Task/Task<T>。您可以等待任何符合等待模式的內容。在實踐中,很少有開發人員需要自己實現這個模式,但它允許像Task.Yield這樣的方法返回YieldAwaitable而不是任務。

+0

- 謝謝喬恩。 –

+0

所以不,它不是「只是」語法糖!看到託管IL。任務與使用和不使用異步/等待之間的區別,你會感到非常驚訝。 – hVostt

+2

@hVostt:我已經反編譯*許多異步/等待代碼。我不會再對這種差異感到驚訝,但我仍然認爲它只是「語法糖」。這是非常有用和相當複雜的句法糖,有時結果是代碼,它不能完全代表使用C#4的IL - 但從根本上說它沒有做任何真正無法完成的事情。這不像泛型,這是類型系統的根本轉變。這只是編譯器很聰明。我並不試圖忽視它的實用性 - 我*愛*異步。但它仍然是語法糖海事組織。 –