1. 程式人生 > >.net 中的async,await理解

.net 中的async,await理解

表示 info 分享圖片 保存 read color 時間 成功 信息

理解:

1、async修飾的方法可理解為異步方法(必須要配合await,否則和普通方法無異)
2、當async方法執行遇到await,則立即將控制權轉移到async方法的調用者
3、由調用者決定是否需要等待async方法執行完再繼續往下執行
4、await會掛起當前方法,即阻塞當前方法繼續往下執行,轉交控制權給調用者

註意:如果調用一個async方 法,卻不使用await關鍵字來標記一個掛起點的話,程序將會忽略async關鍵字並以同步的方式執行。編譯器會對類似的問題發出警告。

例子一:(控制臺程序)

 1         static void Main(string[] args)
2 { 3 MyMain();//由於main方法無法定義成async,顧此定義一個方法MyMain來表示main方法。 4 Console.Read(); 5 } 6 static async void MyMain() 7 { 8 Console.WriteLine("main方法開始執行"); 9 AsyncAction(); 10 Console.WriteLine("main方法繼續執行
"); 11 Console.WriteLine("main方法執行結束"); 12 } 13 14 static async Task<string> AsyncAction() 15 { 16 Console.WriteLine("AsyncAction方法await之前"); 17 string result = await Task<string>.Run(() => 18 { 19 Thread.Sleep(1000
); 20 Console.WriteLine("AsyncAction方法sleep一秒後"); 21 return "AsyncAction的返回值"; 22 }); 23 Console.WriteLine("AsyncAction方法await之後-{0}", result); 24 return result; 25 }

執行結果:技術分享圖片

由返回結果可以知,此異步方法AsyncAction執行遇到await,即程序執行到此行立刻被掛起,將控制權限交給MyMain方法,由MyMain決定是否等待AsyncAction執行完再往下執行,此處由於執行AsyncAction方法前不加await,所以直接往下執行。而AsyncAction方法中的await Task.Run(包括)後的代碼會異步執行。

例子二:例子一中MyMain方法執行AsyncAction前面加await

 1         static void Main(string[] args)
 2         {
 3             MyMain();//由於main方法無法定義成async,顧此定義一個方法MyMain來表示main方法。
 4             Console.Read();
 5         }
 6         static async void MyMain()
 7         {
 8             Console.WriteLine("main方法開始執行");
 9             await AsyncAction();
10             Console.WriteLine("main方法繼續執行");
11             Console.WriteLine("main方法執行結束");
12         }
13 
14         static async Task<string> AsyncAction()
15         {
16             Console.WriteLine("AsyncAction方法await之前");
17             string result = await Task<string>.Run(() =>
18             {
19                 Thread.Sleep(1000);
20                 Console.WriteLine("AsyncAction方法sleep一秒後");
21                 return "AsyncAction的返回值";
22             });
23             Console.WriteLine("AsyncAction方法await之後-{0}", result);
24             return result;
25         }

執行結果:技術分享圖片

由於AsyncAction方法執行前加了await,故MyMain方法要等待其執行結束才繼續往下執行。

使用場景及用法分析:

當有某一操作執行時間較長或者執行結果對整體程序執行影響不大(一般此操作都會是一個獨立一個方法。)主線程的執行不依賴於此操作的執行結果。
常見於一些IO操作,如日誌的記錄,當觸發記錄日誌動作的時候,應該讓其獨立一個線程去執行,此時不管日誌記錄成功與否,
都不應該阻塞主線程的執行。
在上面的例子一中,可以將AsyncAction方法中的 Task.Run 當成記錄日誌的動作,當程序執行到 await Task.Run後,
AsyncAction方法立刻被掛起,主線程MyMain繼續往下執行。
這裏可能有人會疑問?為何不直接在主線程MyMain中直接開啟線程 Task.Run 來記錄日誌?
而是要定義到一個異步方法(此例子為AsyncAction方法)中處理日誌。
是,如果此時只是為了記錄日誌,也不是必須要寫到一個方法中。但是,
首先,這種單一功能的操作,本應該就是獨立寫到一個方法中。
其次是 AsyncAction方法 中的 await Task.Run 的返回值也許還有其他操作。

如下面例子:記錄日誌之前,需要獲取登陸用戶的一些信息,並且將用戶信息一同保存到日誌中,如果寫到主線程MyMain中,則避免不了阻塞主線程(因為需要等待獲取用戶信息)。
當然,你也可以將這兩個方法一起寫到一個方法中由Task調用,這裏只是舉個例子來說明Async和await的用法場景。

 1         static void Main(string[] args)
 2         {
 3             MyMain();//由於main方法無法定義成async,顧此定義一個方法MyMain來表示main方法。
 4             Console.Read();
 5         }
 6         static async void MyMain()
 7         {
 8             Console.WriteLine("main方法開始執行");
 9             WriteUserLog();
10             Console.WriteLine("main方法繼續執行");
11             Console.WriteLine("main方法執行結束");
12         }
13 
14         static async void WriteUserLog()
15         {
16             Console.WriteLine("獲取用戶信息之前");
17             string userInfo = await GetUserInfoAsync(); //盡量早的使用await,以便此方法盡快掛起(異步執行)
18             Console.WriteLine("寫入日誌之前");
19             WriteLog(userInfo);
20         }
21 
22         static Task<string> GetUserInfoAsync()
23         {
24             return Task.Factory.StartNew(() => {
25                 Thread.Sleep(1000);
26                 Console.WriteLine("獲取用戶信息完成");
27                 return "jxf";
28             });
29         }
30 
31         static void WriteLog(string userInfo)
32         {
33             Thread.Sleep(1000);
34             Console.WriteLine("寫入日誌完成,用戶信息:{0}", userInfo);
35         }

執行結果:技術分享圖片

.net 中的async,await理解