程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> [C#] 異步編程,

[C#] 異步編程,

編輯:C#入門知識

[C#] 異步編程,


剖析異步方法

  這是上篇《開始接觸 async/await 異步編程》(入門)的第二章內容,主要是深入了解異步方法,建議大家先看入門篇,很短。

  本文要求了解委托的使用。

 

目錄

 

介紹異步方法

     異步方法:在執行完成前立即返回調用方法,在調用方法繼續執行的過程中完成任務。      語法分析:      (1)關鍵字:方法頭使用 async 修飾。      (2)要求:包含 N(N>0) 個 await 表達式(不存在 await 表達式的話 IDE 會發出警告),表示需要異步執行的任務。【備注】感謝 czcz1024 的修正與補充:沒有的話,就和普通方法一樣執行了。      (3)返回類型:只能返回 3 種類型(void、Task 和 Task<T>)。Task 和 Task<T> 標識返回的對象會在將來完成工作,表示調用方法和異步方法可以繼續執行。      (4)參數:數量不限。但不能使用 out 和 ref 關鍵字。      (5)命名約定:方法後綴名應以 Async 結尾。      (6)其它:匿名方法和 Lambda 表達式也可以作為異步對象;async 是一個上下文關鍵字;關鍵字 async 必須在返回類型前。     關於 async 關鍵字:

  ①在返回類型之前包含 async 關鍵字

  ②它只是標識該方法包含一個或多個 await 表達式,即,它本身不創建異步操作。

  ③它是上下文關鍵字,即可作為變量名。

 

  現在先來著重分析一下這三種返回值類型:void、Task 和 Task<T>

  (1)Task<T>:調用方法要從調用中獲取一個 T 類型的值,異步方法的返回類型就必須是Task<T>。調用方法從 Task 的 Result 屬性獲取的就是 T 類型的值。

1 private static void Main(string[] args) 2 { 3 Task<int> t = Calculator.AddAsync(1, 2); 4 5 //一直在干活 6 7 Console.WriteLine($"result: {t.Result}"); 8 9 Console.Read(); 10 } Program.cs 1 internal class Calculator 2 { 3 private static int Add(int n, int m) 4 { 5 return n + m; 6 } 7 8 public static async Task<int> AddAsync(int n, int m) 9 { 10 int val = await Task.Run(() => Add(n, m)); 11 12 return val; 13 } 14 } View Code 

 

  (2)Task:調用方法不需要從異步方法中取返回值,但是希望檢查異步方法的狀態,那麼可以選擇可以返回 Task 類型的對象。不過,就算異步方法中包含 return 語句,也不會返回任何東西。

1 private static void Main(string[] args) 2 { 3 Task t = Calculator.AddAsync(1, 2); 4 5 //一直在干活 6 7 t.Wait(); 8 Console.WriteLine("AddAsync 方法執行完成"); 9 10 Console.Read(); 11 } Program.cs 1 internal class Calculator 2 { 3 private static int Add(int n, int m) 4 { 5 return n + m; 6 } 7 8 public static async Task AddAsync(int n, int m) 9 { 10 int val = await Task.Run(() => Add(n, m)); 11 Console.WriteLine($"Result: {val}"); 12 } 13 } View Code

圖4

圖5

     

  (3)void:調用方法執行異步方法,但又不需要做進一步的交互。 

1 private static void Main(string[] args) 2 { 3 Calculator.AddAsync(1, 2); 4 5 //一直在干活 6 7 Thread.Sleep(1000); //掛起1秒鐘 8 Console.WriteLine("AddAsync 方法執行完成"); 9 10 Console.Read(); 11 } Program.cs 1 internal class Calculator 2 { 3 private static int Add(int n, int m) 4 { 5 return n + m; 6 } 7 8 public static async void AddAsync(int n, int m) 9 { 10 int val = await Task.Run(() => Add(n, m)); 11 Console.WriteLine($"Result: {val}"); 12 } 13 } Calculator.cs

圖6

圖7

 

一、控制流

     異步方法的結構可拆分成三個不同的區域:      (1)表達式之前的部分:從方法頭到第一個 await 表達式之間的所有代碼。      (2)await 表達式:將被異步執行的代碼。      (3)表達式之後的部分:await 表達式的後續部分。   1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 var t = Do.GetGuidAsync(); 6 t.Wait(); 7 8 Console.Read(); 9 } 10 11 12 private class Do 13 { 14 /// <summary> 15 /// 獲取 Guid 16 /// </summary> 17 /// <returns></returns> 18 private static Guid GetGuid() //與Func<Guid> 兼容 19 { 20 return Guid.NewGuid(); 21 } 22 23 /// <summary> 24 /// 異步獲取 Guid 25 /// </summary> 26 /// <returns></returns> 27 public static async Task GetGuidAsync() 28 { 29 var myFunc = new Func<Guid>(GetGuid); 30 var t1 = await Task.Run(myFunc); 31 32 var t2 = await Task.Run(new Func<Guid>(GetGuid)); 33 34 var t3 = await Task.Run(() => GetGuid()); 35 36 var t4 = await Task.Run(() => Guid.NewGuid()); 37 38 Console.WriteLine($"t1: {t1}"); 39 Console.WriteLine($"t2: {t2}"); 40 Console.WriteLine($"t3: {t3}"); 41 Console.WriteLine($"t4: {t4}"); 42 } 43 } 44 } View Code

圖2-1

圖2-2

   上面 4 個 Task.Run() 都是采用了 Task Run(Func<TReturn> func) 形式。

 

  Task.Run() 支持 4 中不同的委托類型所表示的方法:Action、Func<TResult>、Func<Task> 和 Func<Task<TResult>>

1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 var t = Do.GetGuidAsync(); 6 t.Wait(); 7 8 Console.Read(); 9 } 10 11 private class Do 12 { 13 public static async Task GetGuidAsync() 14 { 15 await Task.Run(() => { Console.WriteLine(Guid.NewGuid()); }); //Action 16 17 Console.WriteLine(await Task.Run(() => Guid.NewGuid())); //Func<TResult> 18 19 await Task.Run(() => Task.Run(() => { Console.WriteLine(Guid.NewGuid()); })); //Func<Task> 20 21 Console.WriteLine(await Task.Run(() => Task.Run(() => Guid.NewGuid()))); //Func<Task<TResult>> 22 } 23 } 24 } View Code

 

三、取消異步操作

 

四、異常處理

 

五、在調用方法中同步地等待任務

 

六、在異步方法中異步地等待任務

 

七、Task.Delay 方法

 

小結

 

傳送門

  入門:《開始接觸 async/await 異步編程》

 


 

--這是預覽版本,最終整理完校對後將放上首頁,不便之處請諒解--

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved