C#基本之異步驟用實例教程。本站提示廣大學習愛好者:(C#基本之異步驟用實例教程)文章只能為提供參考,不一定能成為您想要的結果。以下是C#基本之異步驟用實例教程正文
本文實例情勢展現了C#中異步驟用的完成辦法,並對其道理停止了較為深刻的剖析,現以教程的方法分享給年夜家供年夜家參考之用。詳細以下:
起首我們來看一個簡略的例子:
小明在燒水,等水燒開今後,將開水灌入熱水瓶,然後開端整頓家務
小文在燒水,在燒水的進程中整頓家務,等水燒開今後,放下手中的家務活,將開水灌入熱水瓶,然後持續整頓家務
這也是平常生涯中很罕見的情況,小文的做事效力顯著要高於小明。從C#法式履行的角度斟酌,小明應用的同步處置方法,而小文則應用的異步處置方法。
同步處置方法下,事務是按次序一件一件處置的;而異步方法則是,將子操作從主操作平分離出來,主操作持續停止,子操作在完成處置的時刻告訴主操作。
在C#中,異步經由過程拜托來完成。請看上面的例子:
class Program { static TimeSpan Boil() { Console.WriteLine("水壺:開端燒水..."); Thread.Sleep(6000); Console.WriteLine("水壺:水曾經燒開了!"); return TimeSpan.MinValue; } delegate TimeSpan BoilingDelegate(); static void Main(string[] args) { Console.WriteLine("小文:將水壺放在爐子上"); BoilingDelegate d = new BoilingDelegate(Boil); IAsyncResult result = d.BeginInvoke(BoilingFinishedCallback, null); Console.WriteLine("小文:開端整頓家務..."); for (int i = 0; i < 20; i++) { Console.WriteLine("小文:整頓第{0}項家務...", i + 1); Thread.Sleep(1000); } } static void BoilingFinishedCallback(IAsyncResult result) { AsyncResult asyncResult = (AsyncResult)result; BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate; del.EndInvoke(result); Console.WriteLine("小文:將熱水灌到熱水瓶"); Console.WriteLine("小文:持續整頓家務"); } }
下面的例子是一個最簡略的異步驟用的例子,沒有對異步驟用函數做任何參數傳遞和前往值校驗。這個例子反應了小文燒水的流程,起首小文將水壺放在爐子上,在界說好拜托今後,就應用BeginInvoke辦法開端異步驟用,即讓水壺開端燒水,因而小文便開端整頓家務。水燒開後,C#的異步模子會觸發由BeginInvoke辦法所指定的回調函數,也就是水燒開後的處置邏輯由這個回調函數界說,此時小文將水灌入熱水瓶並持續整頓家務。
因而可知,在C#中完成異步驟用其實其實不龐雜,起首創立一個異步處置函數,並針對其界說一個拜托;然後在挪用函數的時刻,應用拜托的BeginInvoke辦法,指定在函數處置完成時的回調函數(假如不須要對完成事宜做處置,可以給null值),並指定所需的參數(假如沒有參數,也能夠給null值);最初在回調函數中處置完成事宜。
請留意上例回調函數中的EndInvoke挪用,EndInvoke會使得挪用線程壅塞,直到異步函數處置完成。明顯,緊接在BeginInvoke前面的EndInvoke應用方法與同步驟用等價。
EndInvoke挪用的前往值也就是異步處置函數的前往值。我們把法式稍作修正,將Boil辦法改成上面的情勢:
static TimeSpan Boil() { DateTime begin = DateTime.Now; Console.WriteLine("水壺:開端燒水..."); Thread.Sleep(6000); Console.WriteLine("水壺:水曾經燒開了!"); return DateTime.Now - begin; }
然後將BoilingFinishedCallback改成上面的情勢:
static void BoilingFinishedCallback(IAsyncResult result) { AsyncResult asyncResult = (AsyncResult)result; BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate; Console.WriteLine("(燒水一共用去{0}時光)", del.EndInvoke(result)); Console.WriteLine("小文:將熱水灌到熱水瓶"); Console.WriteLine("小文:持續整頓家務"); }
那末我們便可以在EndInvoke的時刻,取得由Boil異步處置函數前往的時光值。現實上,假如界說的BoilingDelegate拜托存在參數列表,那末我們也能夠在BeginInvoke的時刻,將所需的參數傳給異步處置函數。BeginInvoke/EndInvoke函數的簽名與界說它們的拜托簽名有關。
留意:在修正後的BoilingFinishedCallback辦法中,為了獲得拜托實例以便獲得異步處置函數的前往值,我們采取了上面的轉換:
AsyncResult asyncResult = (AsyncResult)result; BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;
如許能力取得挪用異步處置函數的拜托的實體。
.NET處置異步函數挪用,現實上是經由過程線程來完成的。這個進程有以下幾個特色:
1.異步函數由線程完成,這個線程是.NET線程池中的線程
2.平日情形下,.NET線程池具有500個線程(固然這個數目可以設置),每當挪用BeginInvoke開端異步處置時,異步處置函數就由線程池中的某個線程擔任履行,而用戶沒法掌握詳細是由哪一個線程擔任履行
3.因為線程池中線程數目無限,是以當池中線程被完整占用時,新的挪用要求將使函數不能不期待空余線程的湧現。此時,法式的效力會有所影響。
為了驗證這些特色,請看上面的法式:
class Program { delegate void MethodInvoker(); static void Foo() { int intAvailableThreads, intAvailableIoAsynThreds; ThreadPool.GetAvailableThreads(out intAvailableThreads, out intAvailableIoAsynThreds); string strMessage = String.Format(@"Is Thread Pool: {0}, Thread Id: {1} Free Threads {2}", Thread.CurrentThread.IsThreadPoolThread.ToString(), Thread.CurrentThread.GetHashCode(), intAvailableThreads); Console.WriteLine(strMessage); Thread.Sleep(10000); return; } static void CallFoo() { MethodInvoker simpleDelegate = new MethodInvoker(Foo); for (int i = 0; i < 15; i++) { simpleDelegate.BeginInvoke(null, null); } } static void Main(string[] args) { ThreadPool.SetMaxThreads(10, 10); CallFoo(); Console.ReadLine(); } }
這個法式在肇端的時刻將線程池中最年夜線程個數設置為10個,然後做15次異步驟用,每一個異步驟用中都逗留10秒鐘看成處置自己所要消費的時光。從法式的履行我們可以看到,以後10個異步驟用完整開端今後,新的異步驟用就會期待(留意:不是主線程在期待),直到線程池中有線程余暇出來。
願望本文所述對年夜家的C#法式設計有所贊助。