1. 程式人生 > >Async和Await 異步方法

Async和Await 異步方法

標記 命名約定 代碼 結果 num 包含 表達式 方法 執行

Async和Await關鍵字是C#異步編程的核心。通過使用這兩個關鍵字,你可以使用.NET Framework或Windows Runtime的資源創建一個異步方法如同你創建一個同步的方法一樣容易。通過使用async和await定義的異步方法,這裏被稱為異步方法。

異步方法的特點:

方法中包含了 async 修飾符。

一個async方法按照慣例以“Async”結尾。

返回類型是如下類型之一:

Task<TResult> 當你的方法有返回值時,TResult即返回值的類型

Task 當你的方法沒有return語句,或者返回值並不參與任何形式的運算(包括賦值操作)。

Void 當你編寫一個異步事件處理時會用到。

方法通常包括至少一個await的表達式,這意味著該方法在遇到await時不能繼續執行,直到等待異步操作完成。在此期間,該方法將被暫停,並且控制權返回到該方法的調用者。

線程

異步方法的目的是不阻塞操作。在async方法中, await任務在執行的過程中,並不會阻塞當前的線程,其余的方法可以繼續執行,控制權將會移交到async方法的調用者。

async和await關鍵字並不會創建額外的線程,async方法不會去請求多線程操作。真正創建線程的操作是由Task.Run()實現的,一個async方法並不是在他自己的線程上執行的,只有當方法被激活時,才會使用當前線程的上下文和處理時間。

async方法要比BackgroundWorker更實用,而且使用起來更簡單而且不用去過多的考慮競態沖突神馬的。async方法會將運行中的代碼依據某些算法進行合理的拆分,並傳遞給線程池,這也是BackgroundWorker不能比的。

Async和Await

如果需要使用async或者await指定一個異步方法,我們需要註意一下兩點:

用async標記的異步方應該使用await關鍵子來制定掛起點。await操作符會告訴編譯器,這個async方放在完成之前,後面的代碼無法繼續執行,同時,控制權轉移到async方法的調用者。

標記為async的方法,調用時應使用await。

一個async方法裏通常包含一個或多個的對應的await操作符,但如果沒有await表達式也不會導致編譯錯誤。但如果調用一個async方 法,卻不使用await關鍵字來標記一個掛起點的話,程序將會忽略async關鍵字並以同步的方式執行。編譯器會對類似的問題發出警告。

返回類型和參數

在.NET Framework編程中,一個async方法通常返回的類型是Task或者Task<TResult>。在異步方法中,await操作符作用於從另外一個異步方法返回的Task。

如果指定Task<TResult>為返回結果,那麽這個方法必須包含return指定的TResult結果的語句。

如果使用Task作為返回值,那麽這個方法應該不存在使用return語句返回結果的代碼,或者返回的結果不參與任何運算(包括賦值操作)。

每一個返回的task都代表一個正在執行的工作,task包裝的信息中包含了這個異步方法的執行時的狀態,最終的結果,或者處理過程中拋出的異常。

如果返回值為void,這種類型主要使用於定義事件處理。異步事件通常被認為是一系列異步操作的開始。使用void返回類型不需要await,而且調用void異步方法的函數不會捕獲方法拋出的異常。

另外,async方法不能使用ref或者out參數,但是可以調用含有這些參數的方法。

命名約定

按照約定,你應該在異步方法的名稱後面追加“Async”用以標記此方法。但是在event,基類和接口中不需要遵守約定,就像本文例子中event處理函數Button1_Click一樣。

例子:

 1 using System;
 2 using System.Threading.Tasks;
 3  
 4 namespace AsyncAndAwait {
 5     class Program {
 6         static void Main(string[] args) {
 7             DisplayValue();
 8             Console.Write("Myclass End");
 9             Console.Read();
10         }
11  
12  
13         public static Task<double> GetvalueAsync(double num1, double num2) {
14             return Task.Run(() => {
15                 for(int i = 0; i < 10000; i++) {
16                     num1 = num1 / num2;
17  
18                 }
19                 return num1;
20  
21  
22             });
23         }
24         public static async void DisplayValue() {
25             double result = await GetvalueAsync(1234.5, 1.01);
26  
27             Console.Write("Value is:" + result);
28  
29         }
30     }
31 }

Async和Await 異步方法