天天看點

異步程式設計概述

原文:http://hxhbluestar.cnblogs.com/articles/60023.html

.NET Framework 允許您異步調用任何方法。定義與您需要調用的方法具有相同簽名的委托;公共語言運作庫将自動為該委托定義具有适當簽名的 BeginInvoke和 EndInvoke方法。

BeginInvoke方法用于啟動異步調用。它與您需要異步執行的方法具有相同的參數,隻不過還有兩個額外的參數(将在稍後描述)。BeginInvoke立即傳回,不等待異步調用完成。BeginInvoke傳回 IasyncResult,可用于監視調用進度。

EndInvoke方法用于檢索異步調用結果。調用 BeginInvoke 後可随時調用 EndInvoke方法;如果異步調用未完成,EndInvoke将一直阻塞到異步調用完成。EndInvoke的參數包括您需要異步執行的方法的 out和 ref參數(在 Visual Basic 中為 <Out> ByRef 和 ByRef)以及由 BeginInvoke傳回的 IAsyncResult。

注意   Visual Studio .NET 中的智能感覺功能會顯示 BeginInvoke和 EndInvoke的參數。如果您沒有使用 Visual Studio 或類似的工具,或者您使用的是 C# 和 Visual Studio .NET,請參見異步方法簽名擷取有關運作庫為這些方法定義的參數的描述。

本主題中的代碼示範了四種使用 BeginInvoke和 EndInvoke 進行異步調用的常用方法。調用了 BeginInvoke後,可以:

·進行某些操作,然後調用 EndInvoke一直阻塞到調用完成。

·使用 IAsyncResult.AsyncWaitHandle 擷取 WaitHandle,使用它的 WaitOne 方法将執行一直阻塞到發出 WaitHandle信号,然後調用 EndInvoke。

·輪詢由 BeginInvoke傳回的 IAsyncResult,确定異步調用何時完成,然後調用 EndInvoke。

·将用于回調方法的委托傳遞給 BeginInvoke。該方法在異步調用完成後在 ThreadPool 線程上執行,它可以調用 EndInvoke。

警告   始終在異步調用完成後調用 EndInvoke。

測試方法和異步委托

四個示例全部使用同一個長期運作的測試方法 TestMethod。該方法顯示一個表明它已開始處理的控制台資訊,休眠幾秒鐘,然後結束。TestMethod有一個 out參數(在 Visual Basic 中為 <Out> ByRef),它示範了如何将這些參數添加到 BeginInvoke和 EndInvoke 的簽名中。您可以用類似的方式處理 ref參數(在 Visual Basic 中為 ByRef)。

下面的代碼示例顯示 TestMethod以及代表 TestMethod的委托;若要使用任一示例,請将示例代碼追加到這段代碼中。

注意   為了簡化這些示例,TestMethod在獨立于 Main() 的類中聲明。或者,TestMethod可以是包含 Main() 的同一類中的 static方法(在 Visual Basic 中為 Shared)。

異步程式設計概述

using  System;

異步程式設計概述

using  System.Threading; 

異步程式設計概述
異步程式設計概述
異步程式設計概述

public  class  AsyncDemo  {

異步程式設計概述

    // The method to be executed asynchronously.

異步程式設計概述

    //

異步程式設計概述
異步程式設計概述

    public string TestMethod(int callDuration, out int threadId) {

異步程式設計概述

        Console.WriteLine("Test method begins.");

異步程式設計概述

        Thread.Sleep(callDuration);

異步程式設計概述

        threadId = AppDomain.GetCurrentThreadId();

異步程式設計概述

        return "MyCallTime was " + callDuration.ToString();

異步程式設計概述

    }

異步程式設計概述

}

異步程式設計概述
異步程式設計概述

//  The delegate must have the same signature as the method

異步程式設計概述

//  you want to call asynchronously.

異步程式設計概述

public  delegate  string  AsyncDelegate( int  callDuration,  out  int  threadId);

異步程式設計概述
異步程式設計概述

using  System;

異步程式設計概述

using  System.Threading; 

異步程式設計概述
異步程式設計概述
異步程式設計概述

public  class  AsyncDemo  {

異步程式設計概述

    // The method to be executed asynchronously.

異步程式設計概述

    //

異步程式設計概述
異步程式設計概述

    public string TestMethod(int callDuration, out int threadId) {

異步程式設計概述

        Console.WriteLine("Test method begins.");

異步程式設計概述

        Thread.Sleep(callDuration);

異步程式設計概述

        threadId = AppDomain.GetCurrentThreadId();

異步程式設計概述

        return "MyCallTime was " + callDuration.ToString();

異步程式設計概述

    }

異步程式設計概述

}

異步程式設計概述
異步程式設計概述

//  The delegate must have the same signature as the method

異步程式設計概述

//  you want to call asynchronously.

異步程式設計概述

public  delegate  string  AsyncDelegate( int  callDuration,  out  int  threadId);

異步程式設計概述

使用 EndInvoke 等待異步調用

異步執行方法的最簡單方式是以 BeginInvoke開始,對主線程執行一些操作,然後調用 EndInvoke。EndInvoke直到異步調用完成後才傳回。這種技術非常适合檔案或網絡操作,但是由于它阻塞 EndInvoke,是以不要從使用者界面的服務線程中使用它。

異步程式設計概述
異步程式設計概述

public  class  AsyncMain  {

異步程式設計概述
異步程式設計概述

    static void Main(string[] args) {

異步程式設計概述

        // The asynchronous method puts the thread id here.

異步程式設計概述

        int threadId;

異步程式設計概述
異步程式設計概述

        // Create an instance of the test class.

異步程式設計概述

        AsyncDemo ad = new AsyncDemo();

異步程式設計概述
異步程式設計概述

        // Create the delegate.

異步程式設計概述

        AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);

異步程式設計概述
異步程式設計概述

        // Initiate the asychronous call.

異步程式設計概述

        IAsyncResult ar = dlgt.BeginInvoke(3000, 

異步程式設計概述

            out threadId, null, null);

異步程式設計概述
異步程式設計概述

        Thread.Sleep(0);

異步程式設計概述

        Console.WriteLine("Main thread {0} does some work.",

異步程式設計概述

            AppDomain.GetCurrentThreadId());

異步程式設計概述
異步程式設計概述

        // Call EndInvoke to Wait for the asynchronous call to complete,

異步程式設計概述

        // and to retrieve the results.

異步程式設計概述

        string ret = dlgt.EndInvoke(out threadId, ar);

異步程式設計概述
異步程式設計概述
異步程式設計概述

        Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", threadId, ret);

異步程式設計概述

    }

異步程式設計概述

}

異步程式設計概述

使用 WaitHandle 等待異步調用

等待 WaitHandle 是一項常用的線程同步技術。您可以使用由 BeginInvoke傳回的 IAsyncResult 的 AsyncWaitHandle 屬性來擷取 WaitHandle。異步調用完成時會發出 WaitHandle信号,而您可以通過調用它的 WaitOne 等待它。

如果您使用 WaitHandle,則在異步調用完成之後,但在通過調用 EndInvoke檢索結果之前,可以執行其他處理。

異步程式設計概述
異步程式設計概述

public  class  AsyncMain  {

異步程式設計概述
異步程式設計概述

    static void Main(string[] args) {

異步程式設計概述

        // The asynchronous method puts the thread id here.

異步程式設計概述

        int threadId;

異步程式設計概述
異步程式設計概述

        // Create an instance of the test class.

異步程式設計概述

        AsyncDemo ad = new AsyncDemo();

異步程式設計概述
異步程式設計概述

        // Create the delegate.

異步程式設計概述

        AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);

異步程式設計概述
異步程式設計概述

        // Initiate the asychronous call.

異步程式設計概述

        IAsyncResult ar = dlgt.BeginInvoke(3000, 

異步程式設計概述

            out threadId, null, null);

異步程式設計概述
異步程式設計概述

        Thread.Sleep(0);

異步程式設計概述

        Console.WriteLine("Main thread {0} does some work.",

異步程式設計概述

            AppDomain.GetCurrentThreadId());

異步程式設計概述
異步程式設計概述

        // Wait for the WaitHandle to become signaled.

異步程式設計概述

        ar.AsyncWaitHandle.WaitOne();

異步程式設計概述
異步程式設計概述

        // Perform additional processing here.

異步程式設計概述

        // Call EndInvoke to retrieve the results.

異步程式設計概述

        string ret = dlgt.EndInvoke(out threadId, ar);

異步程式設計概述
異步程式設計概述
異步程式設計概述

        Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", threadId, ret);

異步程式設計概述

    }

異步程式設計概述

}

異步程式設計概述

輪詢異步調用完成

您可以使用由 BeginInvoke傳回的 IAsyncResult 的 IsCompleted 屬性來發現異步調用何時完成。從使用者界面的服務線程中進行異步調用時可以執行此操作。輪詢完成允許使用者界面線程繼續處理使用者輸入。

異步程式設計概述
異步程式設計概述

public  class  AsyncMain  {

異步程式設計概述
異步程式設計概述

    static void Main(string[] args) {

異步程式設計概述

        // The asynchronous method puts the thread id here.

異步程式設計概述

        int threadId;

異步程式設計概述
異步程式設計概述

        // Create an instance of the test class.

異步程式設計概述

        AsyncDemo ad = new AsyncDemo();

異步程式設計概述
異步程式設計概述

        // Create the delegate.

異步程式設計概述

        AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);

異步程式設計概述
異步程式設計概述

        // Initiate the asychronous call.

異步程式設計概述

        IAsyncResult ar = dlgt.BeginInvoke(3000, 

異步程式設計概述

            out threadId, null, null);

異步程式設計概述
異步程式設計概述

        // Poll while simulating work.

異步程式設計概述
異步程式設計概述

        while(ar.IsCompleted == false) {

異步程式設計概述

            Thread.Sleep(10);

異步程式設計概述

        }

異步程式設計概述
異步程式設計概述

        // Call EndInvoke to retrieve the results.

異步程式設計概述

        string ret = dlgt.EndInvoke(out threadId, ar);

異步程式設計概述
異步程式設計概述
異步程式設計概述

        Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", threadId, ret);

異步程式設計概述

    }

異步程式設計概述

}

異步程式設計概述

異步調用完成時執行回調方法

如果啟動異步調用的線程不需要處理調用結果,則可以在調用完成時執行回調方法。回調方法在 ThreadPool 線程上執行。

要使用回調方法,必須将代表該方法的 AsyncCallback 委托傳遞給 BeginInvoke。也可以傳遞包含回調方法将要使用的資訊的對象。例如,可以傳遞啟動調用時曾使用的委托,以便回調方法能夠調用 EndInvoke。

異步程式設計概述
異步程式設計概述

public  class  AsyncMain  {

異步程式設計概述

    // Asynchronous method puts the thread id here.

異步程式設計概述

    private static int threadId;

異步程式設計概述
異步程式設計概述
異步程式設計概述

    static void Main(string[] args) {

異步程式設計概述

        // Create an instance of the test class.

異步程式設計概述

        AsyncDemo ad = new AsyncDemo();

異步程式設計概述
異步程式設計概述

        // Create the delegate.

異步程式設計概述

        AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);

異步程式設計概述
異步程式設計概述

        // Initiate the asychronous call.  Include an AsyncCallback

異步程式設計概述

        // delegate representing the callback method, and the data

異步程式設計概述

        // needed to call EndInvoke.

異步程式設計概述

        IAsyncResult ar = dlgt.BeginInvoke(3000,

異步程式設計概述

            out threadId, 

異步程式設計概述

            new AsyncCallback(CallbackMethod),

異步程式設計概述

            dlgt );

異步程式設計概述
異步程式設計概述

        Console.WriteLine("Press Enter to close application.");

異步程式設計概述

        Console.ReadLine();

異步程式設計概述

    }

異步程式設計概述
異步程式設計概述

    // Callback method must have the same signature as the

異步程式設計概述

    // AsyncCallback delegate.

異步程式設計概述
異步程式設計概述

    static void CallbackMethod(IAsyncResult ar) {

異步程式設計概述

        // Retrieve the delegate.

異步程式設計概述

        AsyncDelegate dlgt = (AsyncDelegate) ar.AsyncState;

異步程式設計概述
異步程式設計概述

        // Call EndInvoke to retrieve the results.

異步程式設計概述

        string ret = dlgt.EndInvoke(out threadId, ar);

異步程式設計概述
異步程式設計概述
異步程式設計概述

        Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", threadId, ret);

異步程式設計概述

    }

異步程式設計概述

}

異步程式設計概述