一. async和await簡介編程
PS:簡介多線程
1. async和await這兩個關鍵字是爲了簡化異步編程模型而誕生的,使的異步編程跟簡潔,它自己並不建立新線程,但在該方法內部開啓多線程,則另算。異步
2. 這兩個關鍵字適用於處理一些文件IO操做。async
3. 好處:代碼簡介,把異步的代碼寫成了同步的形式,提升了開發效率。異步編程
壞處:若是使用同步思惟去理解,容易出問題,返回值對不上。spa
二. 幾種用法線程
狀況1:當只有async,沒有await時,方法會有個警告,和普通的多線程方法沒有什麼區別,不存在線程等待的問題。3d
代碼實踐:code
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 }
代碼結果:blog
狀況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,第二個狀況麼有線程等待,結果不許確(即共享變量競用問題)。