程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#基本之異步驟用實例教程

C#基本之異步驟用實例教程

編輯:C#入門知識

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#法式設計有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved