C#中異步和多線程的區別介紹

一、區別和聯系

異步和多線程有什麼區別?其實,異步是目的,而多線程是實現這個目的的方法。異步是說,A發起一個操作後(一般都是比較耗時的操作,如果不耗時的操作就沒有必要異步瞭),可以繼續自顧自的處理它自己的事兒,不用幹等著這個耗時操作返回。.Net中的這種異步編程模型,就簡化瞭多線程編程,我們甚至都不用去關心Thread類,就可以做一個異步操作出來。

異步有的時候用普通的線程,有的時候用系統的異步調用功能。有一些IO操作也是異步的,但是未必需要一個線程來運行。例如:硬件是有DMA功能的,在調用DMA傳輸數據的時候,CPU是不需要執行處理的,隻需要發起傳輸和等待傳輸結束即可。具體到.net平臺,比如Socket的BeginSend,如果是運行在Windows    2000以後的平臺,在底層就會調用異步的完成端口來發送。

.Net中的異步執行其實使用的是異步委托。異步委托將要執行的方法提交到.net的線程池,由線程池中的線程來執行異步方法。

二、適用范圍

  • 當需要執行I/O操作時,使用異步操作更合適。I/O操作不僅包括瞭直接的文件、網絡的讀寫,還包括數據庫操作、Web Service、HttpRequest以及.net Remoting等跨進程的調用。
  • 而線程的適用范圍則是那種需要長時間CPU運算的場合,例如耗時較長的圖形處理和算法執行。

三、異步的一個示例

大傢可能都知道,使用delegate可以“自動”使一個方法可以進行異步的調用。從直覺上來說,我覺得是由編譯器或者CLR使用瞭另外的線程來執行目標方法。到底是不是這樣呢??讓我們來用一段代碼證明一下吧。

delegate void AsyncFoo(int i);

static void Main(string[] args)
{
    PrintCurrThreadInfo("Main()");
    for (int i = 0; i < 10; i++)
    {
        PostAsync();
    }
    Console.ReadLine();
}
///<summary>
/// 輸出當前線程的信息
///</summary>
///<param name="name">方法名稱</param>

static void PrintCurrThreadInfo(string name)
{
    Console.WriteLine("Thread Id of " + name + " is: " + Thread.CurrentThread.ManagedThreadId + ", current thread is "
             + (Thread.CurrentThread.IsThreadPoolThread ? "" : "not ")
             + "thread pool thread.");
}


///<summary>
/// 投遞一個異步調用
///</summary>
static void PostAsync()
{
    AsyncFoo caller = new AsyncFoo(Foo);
    caller.BeginInvoke(1000, new AsyncCallback(FooCallBack), caller);
}

///<summary>
/// 測試方法,Sleep一定時間
///</summary>
///<param name="i">Sleep的時間</param>
static void Foo(int i)
{
    PrintCurrThreadInfo("Foo()");
    Thread.Sleep(i);
}

static void FooCallBack(IAsyncResult ar)
{
    PrintCurrThreadInfo("FooCallBack()");
    AsyncFoo caller = (AsyncFoo)ar.AsyncState;
    caller.EndInvoke(ar);
}

這段代碼代碼的輸出如下:

Thread Id of Main() is: 1, current thread is not thread pool thread.
Thread Id of Foo() is: 3, current thread is thread pool thread.
Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
Thread Id of Foo() is: 3, current thread is thread pool thread.
Thread Id of Foo() is: 4, current thread is thread pool thread.
Thread Id of Foo() is: 5, current thread is thread pool thread.
Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
Thread Id of Foo() is: 3, current thread is thread pool thread.
Thread Id of FooCallBack() is: 4, current thread is thread pool thread.
Thread Id of Foo() is: 4, current thread is thread pool thread.
Thread Id of Foo() is: 6, current thread is thread pool thread.
Thread Id of FooCallBack() is: 5, current thread is thread pool thread.
Thread Id of Foo() is: 5, current thread is thread pool thread.
Thread Id of Foo() is: 7, current thread is thread pool thread.
Thread Id of FooCallBack() is: 3, current thread is thread pool thread.
Thread Id of Foo() is: 3, current thread is thread pool thread.
Thread Id of FooCallBack() is: 4, current thread is thread pool thread.
Thread Id of FooCallBack() is: 6, current thread is thread pool thread.
Thread Id of FooCallBack() is: 5, current thread is thread pool thread.
Thread Id of FooCallBack() is: 7, current thread is thread pool thread.
Thread Id of FooCallBack() is: 3, current thread is thread pool thread.

從輸出可以看出,.net 使用 delegate 來“自動”生成的異步調用是使用瞭另外的線程(而且是線程池線程)。

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持LevelAH。

推薦閱讀: