AwaitAsync(異步和多線程)


參考了一些大佬寫的文章:

https://www.cnblogs.com/yilezhu/p/10555849.html這個大佬寫的文章,我還是很喜歡的

https://www.cnblogs.com/mushroom/p/4575417.html

https://blog.csdn.net/dyllove98/article/details/9735955這篇文章是討論在.NET中使用進程內COM組件時的公寓模型,以一個示例直觀演示STAThread和MTAThread的作用和區別。

 

C#5.0,.NET Framework4.5

async/await是語法糖,本身就跟編譯器提供的功能。

在winform中,是一個STAThread

 

 

 在winform中使用await/async偶爾會出現一些意外,所以不建議在winform中使用await/async

  await/async關鍵字,在任何一個方法都可以增加async,await放在Task前面,一般成對出現,只有async是沒有意義的,有警告,只有await的時候會報錯,編譯直接報錯,await/async要么不用,要么用到底。  

  主線程調用async/await方法,主線程遇到await返回只能后續動作,await后面的代碼會等着task任務完成后再繼續執行,await是主線程完成的,其實就像是把await后面的代碼包裝成一個continue的回調動作,然后這個回調動作也可能是task線程,也可能是新的子線程,也可能是主線程。

  一個async方法,如果沒有返回值,可以方法聲明返回Task

 private static async Task<long> SumAsync()
 {
     Console.WriteLine($"SumAsync 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
     long result = 0;

     await Task.Run(() =>
     {
         for (int k = 0; k < 10; k++)
         {
             Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
             Thread.Sleep(1000);
         }
         for (long i = 0; i < 999_999_999; i++)
         {
             result += i;
         }
     });

     Console.WriteLine($"SumFactory 111   end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
     await Task.Run(() =>
     {
         for (int k = 0; k < 10; k++)
         {
             Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
             Thread.Sleep(1000);
         }
         for (long i = 0; i < 999999999; i++)
         {
             result += i;
         }
     });

     Console.WriteLine($"SumFactory 111   end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

     await Task.Run(() =>
     {
         for (int k = 0; k < 10; k++)
         {
             Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
             Thread.Sleep(1000);
         }

         for (long i = 0; i < 999999999; i++)
         {
             result += i;
         }
     });

     Console.WriteLine($"SumFactory 111   end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

     return result;
 }
Task<long> t = SumAsync();
Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

 

 有了await之后,在這個方法中,代碼是按照順序從上往下執行的,但是,為什么不直接寫一個同步方法,還要寫await呢?

  如果不寫await的話,Task.Run()會開啟一個線程,不會足額色主線程,這樣在最后的結果result就是0了。

await/async能夠用同步的方式編寫代碼,但是又是非阻塞的。

 

原理探究和使用建議:

 public class AwaitAsyncILSpy
 {
     public static void Show()
     {
         Console.WriteLine($"start1 {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
         Async();
         Console.WriteLine($"aaa2 {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
     }
     public static async void Async()
     {
         Console.WriteLine($"ddd5 {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
         await Task.Run(() =>
         {
             Thread.Sleep(500);
             Console.WriteLine($"bbb3 {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
         });
         Console.WriteLine($"ccc4 {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
     }
 }
 AwaitAsyncLibrary.AwaitAsyncILSpy.Show();
 Console.WriteLine("hello word!");

這樣的代碼,輸出的順序是是什么?

 

 await/async能夠用同步的方式編寫代碼,但又是非阻塞的

 

 

async方法在編譯之后會生成一個狀態機(實現了IAsyncStateMachine接口)

狀態機:初始化狀態----執行就修改狀態1-----再執行就修改狀態變為0-----執行就修改狀態變為1----如果出現其他狀態就結束了。

就像是紅綠燈那樣,永遠的死循環下去。

  async方法里面的邏輯其實都放在了MoveNext----主線程new一個狀態機1-----主線程調用MoveNext-----指向了await之前的東西----啟動Task----主線程改狀態為0----回去干自己的事了-----子線程Movenext----狀態又回歸-1了-----再執行后續的邏輯------如果需要還可以繼續循環。

 


免責聲明!

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



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