標籤:write star 使用 generic 恢複 優勢 log 殭屍 影響
1.實踐代碼全記錄:
using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;namespace await_測試{ class Program { static void Main(string[] args) { testc(); Console.Read(); } //async具有殭屍病毒般的傳染性,async 會感染周圍的代碼,直到頂層。其實我們只需要順其自然,讓所有代碼都傳染上非同步特性即可。 //如果我們使用Task.Wait 或者Task.Result去試圖阻塞async 的傳播,往往便會自找苦吃。 //這個往往是剛接觸async 非同步人最容易犯的錯誤,這樣往往會導致死結。互相等待。 static async void testc() { ////----寫法1. //Stopwatch sw = new Stopwatch(); //sw.Start(); //var d1 = delay10();//立刻執行,等待取回結果 //var d2 = delay20();//立刻執行,等待取回結果 //var d3 = delay30();//立刻執行,等待取回結果 ////依次取結果,取結果時間很短 //await d1;// 單條語句的確沒有意義,但類似本情境多條語句的話,非同步並發執行的優勢就出來了。總耗時是最長耗時的那個值。 //await d2;// 第一個執行完,取不取結果是另一回事。 //await d3;// 並發執行,【2】需要獲得值的時候,禁用Task.Wait or Task.Result 用 await,防止 異常資訊以及防止死結 //sw.Stop(); //Console.WriteLine("結束"); //Console.WriteLine("耗時:" + sw.ElapsedMilliseconds); ////結論:互不影響,同時進行,耗時約25秒 ////----寫法2. //Stopwatch sw = new Stopwatch(); //sw.Start(); //await delay10();//線性執行,線性取回結果 //await delay20();//線性執行,線性取回結果 //await delay30();//線性執行,線性取回結果 //sw.Stop(); //Console.WriteLine("耗時:" + sw.ElapsedMilliseconds); ////結論:耗時是43秒,線性按行執行,總耗時大於三個線程耗時之和。 ////----寫法3. //Stopwatch sw = new Stopwatch(); //sw.Start(); //Task t1 = delay10();//立刻執行, //Task t2= delay20(); //立刻執行, //Task t3 = delay30();//立刻執行, //Task[] tk = { t1, t2, t3 }; //await Task.WhenAll(tk); //sw.Stop(); //Console.WriteLine("耗時:" + sw.ElapsedMilliseconds); //////結論:互不影響,同時進行,耗時約25秒 //----寫法4. //Stopwatch sw = new Stopwatch(); //sw.Start(); //Task t1 = delay10();//立刻執行, //Task t2 = delay20(); //立刻執行, //Task t3 = delay30();//立刻執行, //Task[] tk = { t1, t2, t3 }; //Task.WaitAll(tk); //注意:【1】需要等待所有任務完成 禁用Task.WaitAll 用 await Task.WhenAll,防止 異常資訊以及防止死結 //http://www.cnblogs.com/bnbqian/p/4513192.html //sw.Stop(); //Console.WriteLine("耗時:" + sw.ElapsedMilliseconds); //////結論:互不影響,同時進行,耗時約25秒 ////總結: 進化過程:Thread+線程同步訊號量 -> Task -> async&await } static async Task delay10() { Task<string> t = new Task<string>(() => { Thread.Sleep(25000);//小失誤。需要等待請用:Task.Delay(),禁用Thread.Sleep,防止 異常資訊以及防止死結 return "25000"; }); t.Start(); string tr = await t; Console.WriteLine(tr); } static async Task delay20() { Task<string> t = new Task<string>(() => { Thread.Sleep(10000); return "10000"; }); t.Start(); string tr = await t; Console.WriteLine(tr); } static async Task delay30() { Task<string> t = new Task<string>(() => { Thread.Sleep(3600); return "3600"; }); t.Start(); string tr = await t; Console.WriteLine(tr); } }}
2.實踐筆記:
1.無論方法是同步還是非同步都可以用async關鍵字來進行標識,因為用async標識只是顯示表明在該方法內可能會用到await關鍵字使其變為非同步方法呼叫,而且將該非同步方法呼叫進行了明確的劃分,只有用了await關鍵字時才是非同步作業,其餘一併為同步操作。
2.當用async標識方法時只是顯示告訴編譯器在該方法中await關鍵字可能會被用到,當執行到await關鍵字開始處於掛起的狀態知道非同步動作執行完成才恢複。
3.用async標識方法並不會影響方法運行完成是否是同步或者非同步,相反,它能夠將方法劃分成多塊,有可能有些在非同步中運行,以至於這些方法是非同步完成的,而劃分非同步和同步方法的邊界就是使用await關鍵字。也就是說如果在方法中未用到await關鍵字時則該方法就是一整塊沒有所謂的劃分,會在同步中運行,在同步中完成。
【筆記】記一次.net文法await和async的非同步編程實驗與筆記。