async、await是在C# 5.0以後引入的一種簡化異步操做的方式。使用它們以後,能夠使咱們的編寫異步操做更加方便快捷,維護以及閱讀起來更方便。api
async、await雖然簡化了咱們編寫異步方法。但也很容易讓人產生誤解。首先看一個例子:異步
public static async Task<int> AddAsync(int x, int y) { return await Task.Factory.StartNew(() => { return x + y; }); }
這種加了async、await叫不叫異步呢?答案確定不是的。咱們能夠這樣叫這種方法:加了async、await標記的同步方法。async
再看下面的一個例子ide
原文:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index 網站
// Three things to note in the signature: // - The method has an async modifier. // - The return type is Task or Task<T>. (See "Return Types" section.) // Here, it is Task<int> because the return statement returns an integer. // - The method name ends in "Async." async Task<int> AccessTheWebAsync() { // You need to add a reference to System.Net.Http to declare client. HttpClient client = new HttpClient(); // GetStringAsync returns a Task<string>. That means that when you await the // task you'll get a string (urlContents). Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); // You can do work here that doesn't rely on the string from GetStringAsync. DoIndependentWork(); // The await operator suspends AccessTheWebAsync. // - AccessTheWebAsync can't continue until getStringTask is complete. // - Meanwhile, control returns to the caller of AccessTheWebAsync. // - Control resumes here when getStringTask is complete. // - The await operator then retrieves the string result from getStringTask. string urlContents = await getStringTask; // The return statement specifies an integer result. // Any methods that are awaiting AccessTheWebAsync retrieve the length value. return urlContents.Length; }
上面的方法GetStringAsync,若是不須要返回值,能夠移步進行執行,而後會執行方法DoIndependentWork方法,知道await getStringTask拿到GetStringAsync方法的返回值。ui
如下特徵總結了使上一個示例成爲異步方法的緣由。url
方法簽名包含 async
修飾符。spa
按照約定,異步方法的名稱以「Async」後綴結尾。code
返回類型爲下列類型之一:blog
若是你的方法有操做數爲 TResult 類型的返回語句,則爲 Task<TResult>。
若是你的方法沒有返回語句或具備沒有操做數的返回語句,則爲 Task。
Void
:若是要編寫異步事件處理程序。
包含 GetAwaiter
方法的其餘任何類型(自 C# 7 起)。
有關詳細信息,請參見本主題後面的「返回類型和參數」。
方法一般包含至少一個 await 表達式,該表達式標記一個點,在該點上,直到等待的異步操做完成方法才能繼續。 同時,將方法掛起,而且控件返回到方法的調用方。 本主題的下一節將解釋懸掛點發生的狀況。
在異步方法中,可以使用提供的關鍵字和類型來指示須要完成的操做,且編譯器會完成其他操做,其中包括持續跟蹤控件以掛起方法返回等待點時發生的狀況。 一些常規流程(例如,循環和異常處理)在傳統異步代碼中處理起來可能很困難。 在異步方法中,元素的編寫頻率與同步解決方案相同且此問題獲得解決。
上面的方法執行過程
關係圖中的數值對應於如下步驟。
事件處理程序調用並等待 AccessTheWebAsync
異步方法。
AccessTheWebAsync
可建立 HttpClient 實例並調用 GetStringAsync 異步方法如下載網站內容做爲字符串。
GetStringAsync
中發生了某種狀況,該狀況掛起了它的進程。 可能必須等待網站下載或一些其餘阻止活動。 爲避免阻止資源,GetStringAsync
會將控制權出讓給其調用方 AccessTheWebAsync
。
GetStringAsync
返回 Task<TResult>,其中 TResult
爲字符串,而且 AccessTheWebAsync
將任務分配給 getStringTask
變量。 該任務表示調用 GetStringAsync
的正在進行的進程,其中承諾當工做完成時產生實際字符串值。
因爲還沒有等待 getStringTask
,所以,AccessTheWebAsync
能夠繼續執行不依賴於 GetStringAsync
得出的最終結果的其餘工做。 該任務由對同步方法 DoIndependentWork
的調用表示。
DoIndependentWork
是完成其工做並返回其調用方的同步方法。
AccessTheWebAsync
已用完工做,能夠不受 getStringTask
的結果影響。 接下來,AccessTheWebAsync
須要計算並返回該下載字符串的長度,但該方法僅在具備字符串時才能計算該值。
所以,AccessTheWebAsync
使用一個 await 運算符來掛起其進度,並把控制權交給調用 AccessTheWebAsync
的方法。 AccessTheWebAsync
將 Task<int>
返回給調用方。 該任務表示對產生下載字符串長度的整數結果的一個承諾。
簡單一句話,並非全部的加了async和await關鍵字的方法就是異步方法。能夠這樣理解 await 的位置決定了究竟是不是異步方法,若是直接await xxxAsync那麼是掛起當前方法直到拿到返回值纔會執行下面的邏輯,這樣就是一種同步方法了。異步是相似這樣的 代碼塊:
task t=xxAsync(); //其它業務邏輯 await t; //結束
參考文章
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index 這篇文章對async、await介紹的很是詳細,不懂的能夠參考這個。