2013-07-06 64 views
4

我正在嘗試新的異步和等待關鍵字。我公司生產的以下異步函數:當您在返回之前等待任務時會發生什麼?

private async static Task<string> GetStringAsync(string pageAddress) 
{ 
    HttpClient client = new HttpClient(); 
    return client.GetStringAsync(pageAddress); 
} 

我明白,我返回Task<String>並且可以等待來自另一個方法的結果。此方法工作正常。我的問題是會發生什麼(因爲它是引擎蓋下),當我用以下內容替換上述功能的第二行(注意引進等待關鍵字):

return await client.GetStringAsync(pageAddress); 

的功能完全相同的行爲一樣的方法!請記住函數返回Task<string>而不是stringawait關鍵字在這裏退化嗎?編譯器是否簡單地從我的代碼中刪除它?

+0

檢查此鏈接http://blogs.msdn.com/b/csharpfaq/archive/2012/06/26/understanding-a-simple-async-program.aspx – MEYWD

+4

你確定第一個版本編譯? –

回答

6

Eric Lippert指出,第一個版本不會編譯;你必須刪除async關鍵字,否則你會得到一個類型錯誤。

下面是關於asyncawait關鍵字如何與返回類型工作的有益心智模式:

  • 通過async方法返回的任何值T被「包裝」成Task<T>
  • await關鍵字(您可以將其視爲運營商)應用於Task<T>時,將「打開」該關鍵字,從而產生T類型的值。

現在,這是一個極端的簡化;實際發生的事情更加複雜。例如,這種簡化跳過了await如何與當前SynchronizationContext一起工作:在第二個示例中,該方法將在await完成後嘗試返回到原始上下文,因此如果該上下文繁忙,您將觀察到不同的行爲。

但大部分情況下,這兩個例子幾乎是等價的。第二個效率較低,因爲狀態機爲async,並在上下文中恢復。

我有一個async/await intro,你可能會發現有幫助;在那篇文章中,我試圖用一種不是的方式來解釋async複雜,但實際上也不是不正確。 :)

7

對於這個問題的回答太大,無法在此處發佈,因爲您目前的理解水平可能很高。你應該做的是先閱讀我的MSDN文章,然後閱讀Mads的MSDN文章;他們是該功能的一個很好的入門介紹,Mads描述了它是如何實現的。你可以在這裏找到鏈接:

http://blogs.msdn.com/b/ericlippert/archive/2011/10/03/async-articles.aspx

然後,如果你有興趣的理論,你應該通過閱讀我所有的文章上延續傳遞風格啓動功能底層:從

http://blogs.msdn.com/b/ericlippert/archive/tags/continuation+passing+style/

開始底端。一旦你理解延續的概念,然後你可以看我的系列文章對我們如何設計異步功能:

http://blogs.msdn.com/b/ericlippert/archive/tags/async/

+0

喬恩斯威特關於異步的系列也很不錯:http://msmvps.com/blogs/jon_skeet/archive/tags/Eduasync/default.aspx – argaz

+0

我將在即將到來的日子裏閱讀你和Jon的博客文章。謝謝。 –

2

埃裏克顯然是這裏的專家,他的建議是合理的,但回答你具體問題:

在第一個版本,在方法async關鍵字是不相關的,你的GetStringAsync方法返回一個由真實退還client.GetStringAsync相同Task<string> awaitable。

在第二個版本,在方法async關鍵字,因爲你使用的方法await和所需的await關鍵字創建並返回一個單獨Task<string> awaitable從client.GetStringAsync完成完成一次awaitable。當發生這種情況時,await然後評估爲由異步方法返回的client.GetStringAsync異步獲得的字符串。

因此對於GetStringAsync的調用者,它們在功能上是相同的,但第一個版本更清晰。

相關問題