參考了一些大佬寫的文章:html
http://www.javashuo.com/article/p-wkkdrrxi-ck.html這個大佬寫的文章,我仍是很喜歡的async
http://www.javashuo.com/article/p-akgxzveo-hx.htmlspa
https://blog.csdn.net/dyllove98/article/details/9735955這篇文章是討論在.NET中使用進程內COM組件時的公寓模型,以一個示例直觀演示STAThread和MTAThread的做用和區別。.net
C#5.0,.NET Framework4.5線程
async/await是語法糖,自己就跟編譯器提供的功能。3d
在winform中,是一個STAThreadcode
在winform中使用await/async偶爾會出現一些意外,因此不建議在winform中使用await/asyncorm
await/async關鍵字,在任何一個方法均可以增長async,await放在Task前面,通常成對出現,只有async是沒有意義的,有警告,只有await的時候會報錯,編譯直接報錯,await/async要麼不用,要麼用到底。 htm
主線程調用async/await方法,主線程遇到await返回只能後續動做,await後面的代碼會等着task任務完成後再繼續執行,await是主線程完成的,其實就像是把await後面的代碼包裝成一個continue的回調動做,而後這個回調動做也多是task線程,也多是新的子線程,也多是主線程。blog
一個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了-----再執行後續的邏輯------若是須要還能夠繼續循環。