第十節:利用async和await簡化異步編程模式的幾種寫法


一. async和await簡介

PS:簡介

1. async和await這兩個關鍵字是為了簡化異步編程模型而誕生的,使的異步編程跟簡潔,它本身並不創建新線程,但在該方法內部開啟多線程,則另算。

2. 這兩個關鍵字適用於處理一些文件IO操作。

3. 好處:代碼簡介,把異步的代碼寫成了同步的形式,提高了開發效率。

 壞處:如果使用同步思維去理解,容易出問題,返回值對不上。

 

二. 幾種用法

情況1:當只有async,沒有await時,方法會有個警告,和普通的多線程方法沒有什么區別,不存在線程等待的問題。

代碼實踐:

 1  private static async void Test1()
 2         {
 3             //主線程執行
 4             Console.WriteLine("主線程{0}開始:", Thread.CurrentThread.ManagedThreadId);
 5             //啟動新線程完成任務
 6             Task task = Task.Run(() =>
 7             {
 8                 Console.WriteLine("子線程{0}開始:", Thread.CurrentThread.ManagedThreadId);
 9                 Thread.Sleep(3000);
10                 Console.WriteLine("子線程{0}結束:", Thread.CurrentThread.ManagedThreadId);
11             });
12             //主線程執行
13             Console.WriteLine("主線程{0}結束:", Thread.CurrentThread.ManagedThreadId);
14         }

代碼結果:

情況2:不推薦void返回值,使用Task來代替Task和Task<T>能夠使用await, Task.WhenAny, Task.WhenAll等方式組合使用,async Void 不行。

代碼實踐:

 1         /// <summary>
 2         /// 不推薦void返回值,使用Task來代替
 3         /// Task和Task<T>能夠使用await, Task.WhenAny, Task.WhenAll等方式組合使用。async Void 不行
 4         /// </summary>
 5         private static async void Test2()
 6         {
 7             //主線程執行
 8             Console.WriteLine("主線程{0}開始:", Thread.CurrentThread.ManagedThreadId);
 9             //啟動新線程完成任務
10             Task task = Task.Run(() =>
11             {
12                 Console.WriteLine("子線程{0}開始:", Thread.CurrentThread.ManagedThreadId);
13                 Thread.Sleep(3000);
14                 Console.WriteLine("子線程{0}結束:", Thread.CurrentThread.ManagedThreadId);
15             });
16             await task;   //等待子線程執行完畢,方可執行后面的語句
17             Console.WriteLine("主線程{0}結束:", Thread.CurrentThread.ManagedThreadId);
18         }

代碼結果:

 

情況3:async Task == async void。 區別:Task和Task<T>能夠使用await, Task.WhenAny, Task.WhenAll等方式組合使用,async Void 不行。

代碼實踐:

 1          /// <summary>
 2         /// 無返回值  async Task == async void
 3         /// Task和Task<T>能夠使用await, Task.WhenAny, Task.WhenAll等方式組合使用,async Void 不行
 4         /// </summary>
 5         private static async Task Test3()
 6         {
 7             //主線程執行
 8             Console.WriteLine("主線程{0}開始:", Thread.CurrentThread.ManagedThreadId);
 9             //啟動新線程完成任務
10             Task task = Task.Run(() =>
11             {
12                 Console.WriteLine("子線程{0}開始:", Thread.CurrentThread.ManagedThreadId);
13                 Thread.Sleep(3000);
14                 Console.WriteLine("子線程{0}結束:", Thread.CurrentThread.ManagedThreadId);
15             });
16             await task;   //等待子線程執行完畢,方可執行后面的語句
17             Console.WriteLine("主線程{0}結束:", Thread.CurrentThread.ManagedThreadId);
18         }

 

代碼結果:

 

情況4和情況5:說明要使用子線程中的變量,一定要等子線程執行結束后再使用。

代碼實踐:

 

 1         /// <summary>
 2         /// 帶返回值的Task,要使用返回值,一定要等子線程計算完畢才行
 3         /// </summary>
 4         /// <returns></returns>
 5         private static async Task<long> Test4()
 6         {
 7             //主線程執行
 8             Console.WriteLine("主線程{0}開始:", Thread.CurrentThread.ManagedThreadId);
 9             long result = 0;
10             //啟動新線程完成任務
11             Task task = Task.Run(() =>
12             {
13                 for (long i = 0; i < 100; i++)
14                 {
15                     result += i;
16                 }
17             });
18             await task;   //等待子線程執行完畢,方可執行后面的語句
19             Console.WriteLine("主線程{0}結束:", Thread.CurrentThread.ManagedThreadId);
20             Console.WriteLine("result:{0}", result);
21             return result;
22         }

 

 1         /// <summary>
 2         /// 帶返回值的Task,要使用返回值,一定要等子線程計算完畢才行
 3         /// 與情況四形成對比,沒有等待,最終結果不准確
 4         /// </summary>
 5         /// <returns></returns>
 6         private static Task<long> Test5()
 7         {
 8             //主線程執行
 9             Console.WriteLine("主線程{0}開始:", Thread.CurrentThread.ManagedThreadId);
10             long result = 0;
11             //啟動新線程完成任務
12             TaskFactory taskFactory = new TaskFactory();
13             Task<long> task = taskFactory.StartNew<long>(() =>
14             {
15                 for (long i = 0; i < 100; i++)
16                 {
17                     result += i;
18                 }
19                 return 1;
20             });
21             Console.WriteLine("主線程{0}結束:", Thread.CurrentThread.ManagedThreadId);
22             Console.WriteLine("result:{0}", result);
23             return task;
24         }

代碼結果:

   以上兩種情況,第一種情況含有線程等待的結果為4950,第二個情況么有線程等待,結果不准確(即共享變量競用問題)。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM