c#进阶(7)—— 异步编程基础(async 和 await 关键字)
async 和 await 關鍵字只是編譯器功能,編譯器會用Task類創建代碼。
返 回值是一個Task,這種返回新線程的方法雖然可以提高系統的響應能力,但是多線程取值會給編碼帶來不便,所以新出的關鍵字await用于阻塞當前線程并 獲取目標線程的返回值,在方法體中使用await關鍵字后要求將方法聲明為async用來表示該方法是異步的,并且返回值必須為void或者將返回者封裝 在一個Task中
1、創建任務
同步方法Greeting ,該方法等待一段時間后,返回一個字符串,通過GetHashCode 查看當前線程ID
代碼如下:
static string Greeting(string name){Task.Delay(3000).Wait();int j = Task.CurrentId.GetHashCode();Console.WriteLine("name" + name);int i =Thread.CurrentThread.GetHashCode();Thread.Sleep(3000);Console.WriteLine("Task 的線程HASHCODE是: " + j);Console.WriteLine("Thread 的線程HASHCODE是" + i);Console.ReadLine();Thread.Sleep(3000);return $"Hello,{name}";}定義方法GreetingAsync,可以使方法異步化,基于任務的異步模式指定,在異步方法名后加上Async后綴,并返回一個任務,異步方法GreetingAsync 和 同步方法Greeting具有相同的輸入參數,但是異步方法返回的是Task<string>,Task<string> 定義了一個返回字符串的任務。代碼如下所示:
/// <summary>/// 異步調用方法/// </summary>/// <param name="name"></param>/// <returns></returns>static Task<string> GreetingAsync(string name){return Task.Run<string>(()=>{return Greeting(name);});}2、調用異步方法
可以使用await 關鍵字來調用返回任務的異步方法GreetingAsync,使用await 關鍵字需要用async修飾符聲明的方法,在GreetingAsync方法完成前,該方法內其他代碼不會繼續執行,但是啟動
CallerWithAsync方法的線程可以被重用,該線程沒有阻塞。
代碼如下所示:
class Program{static void Main(string[] args){CallerWithAsync();}/// <summary>/// 調用異步方法/// </summary>private async static void CallerWithAsync(){string result = await GreetingAsync("chenk");Console.WriteLine(result);}?3、延時任務
GreetingAsync 方法返回一個Task<string> 對象,對象包含任務創建的信息,并保存到任務完成,Task類的ContinueWith 方法定義了任何完成后就調用的代碼,指派給ContinueWith方法的委托,將已完成的任務作為參數傳入,使用Result屬性,可以訪問任務返回的結果。代碼如下:
/// <summary>/// 延續任務/// </summary>private static void CallerWithContinuationTask(){Task<string> t1 = GreetingAsync("chenk");//編譯器把await 關鍵字后的代碼放進ContinueWith 方法的代碼塊轉換await關鍵字t1.ContinueWith(t =>{string result = t.Result;Console.WriteLine("CallerWithContinuationTask 線程Id :" + Thread.CurrentThread.GetHashCode() + "; result 的值為:" +result);Console.ReadLine();});}4、同步上下文
驗證方法中使用的線程,可以點擊‘啟動’——在‘調試’中選擇‘線程’,即可查看當前異步程序運行的線程數及位置,以CallerWithContinuationTask為例,可以看到一個線程為主線程、一個線程在調用GreetingAsync方法、一個線程在執行ContinueWith方法內的代碼堆。截圖如下:
?
5、使用多個異步方法
5.1 按順序調用多個異步方法
使用await 關鍵字可以調用每個異步方法,如果一個異步方法依賴于另一個異步方法的結果,await關鍵字就非常有用。
本例中,GreetingAsync 異步方法的第二次調用完全獨立于第一次調用的結果,如果每個異步方法都不使用await,那么整個MultipleAsyncMethods異步方法將更快返回結果。代碼如下:
private async static void MutipleAsyncMethods(){string s1 = await GreetingAsync("chenk");string s2 = await GreetingAsync("zhangf");Console.WriteLine("Finished both methods \nResult 1:" + s1 + "\nResult 2:" + s2);Console.ReadLine();}5.2 使用組合器
如果異步方法不依賴于其他異步方法,則每個異步方法都不使用await ,而是把每個異步方法的返回結果賦值給Task變量,就會運行的更快,GreetingAsync方法返回Task<string>。這些方法現在可以并行執行了。
組合器可以幫助實現這一點,一個組合器可以接受多個同一類型的參數,并返回同一類型的值,多個同一類型的參數被組合成一個參數傳遞,Task組合器接受多個Task對象作為參數,并返回一個Task。
示例代碼采用Task.WhenAll組合器方法,它可以等待,直到兩個任務都完成。代碼如下:
/// <summary>/// 組合器 WhenAll/// </summary>private async static void MultipleAsyncMethodWithCombinatoral(){Task<string> t1 = GreetingAsync("chenk");Task<string> t2 = GreetingAsync("zhangf");//WhenAll 組合器,從WhenAll方法返回的Task,是在所有傳入方法的任務都完成了才會返回Task。//WhenAny 組合器,是在其中一個傳入方法的任務完成了就會返回Task。await Task.WhenAll(t1, t2);}/// <summary>/// 組合器WhenAll 重載,如果所有的任務返回相同的類型,那么該類型的數組可用于await返回的結果/// </summary>private async static void MultipleAsyncMethodWithCombinatoral2(){Task<string> t1 = GreetingAsync("chenk");Task<string> t2 = GreetingAsync("zhangf");string[] result = await Task.WhenAll(t1, t2);}總結
以上是生活随笔為你收集整理的c#进阶(7)—— 异步编程基础(async 和 await 关键字)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浦发云闪付卡怎么申请?浦发云闪付卡问题分
- 下一篇: 今年油价第一涨要来?国际油价站上40美元