.net 中的async,await理解

理解:異步

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

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

例子一:(控制檯程序)線程

 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         }

執行結果:3d

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

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

 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         }

執行結果:blog

因爲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         }

執行結果:

相關文章
相關標籤/搜索