C# 異步委託 (轉)最近學習這個,所以收集了些

 

當我們的程序順序執行的時候,如果我們調用了一個很耗時的方法,那麼應用程序會使當前的線程處於阻塞狀態,直到方法的調用完成再繼續執行。這樣的方法調用被認爲是同步的。如果我們調用了一個遠程的方法,那麼這個方法的調用可能花費的時間會更長。如果我們不想立即取得方法所返回的結果,或者我們根本就不讓方法返回結果的話,這種等待是沒有必要的。

      如果我們想調用一個這樣的方法,當調用之後就立即返回,假如在調用期間發生了異常,我們可以在稍後的時間重起該方法的動作。那我們就可以利用異步委託來把我們的方法做成異步的調用。

       每個委託都有三個方法:Invoke、BeginInvoke、EndInvoke。

         第一個方法是委託指定函數的同步調用,另外兩個是異步調用。

       如果我們自己寫了個委託

public delegate string MyDelegate(string name);

       那麼C#就會自動爲我們提供了下面兩個方法:

IAsyncResult BeginInvoke(string name,AsyncResult callback,Object o)

        以及

string EndInvoke(IAsyncResult result);

 

以上內容摘自http://www.cnblogs.com/wenwuxianren/archive/2008/04/17/1158504.html

http://www.cnblogs.com/everx/archive/2007/02/01/519218.html

 

下面是MSDN上的官方解釋

        異步委託提供以異步方式調用同步方法的能力。當同步調用一個委託時,“Invoke”方法直接對當前線程調用目標方法。如果編譯器支持異步委託,則它將生成“Invoke”方法以及“BeginInvoke”和“EndInvoke”方法。如果調用“BeginInvoke”方法,則公共語言運行庫 (CLR) 將對請求進行排隊並立即返回到調用方。將對來自線程池的線程調用該目標方法。提交請求的原始線程自由地繼續與目標方法並行執行,該目標方法是對線程池線程運行的。如果在對“BeginInvoke”方法的調用中指定了回調方法,則當目標方法返回時將調用該回調方法。在回調方法中,“EndInvoke”方法獲取返回值和所有輸入/輸出參數。如果在調用“BeginInvoke”時未指定任何回調方法,則可以從調用“BeginInvoke”的線程中調用“EndInvoke”。

       .NET Framework 允許您異步調用任何方法。爲此,應定義與您要調用的方法具有相同簽名的委託;公共語言運行庫會自動使用適當的簽名爲該委託定義 BeginInvoke 和 EndInvoke 方法。

       BeginInvoke 方法可啓動異步調用。它與您需要異步執行的方法具有相同的參數,另外它還有兩個可選參數。第一個參數是一個 AsyncCallback 委託,該委託引用在異步調用完成時要調用的方法。第二個參數是一個用戶定義的對象,該對象可向回調方法傳遞信息。BeginInvoke 立即返回,不等待異步調用完成。BeginInvoke 會返回 IAsyncResult,這個結果可用於監視異步調用進度。

EndInvoke 方法檢索異步調用的結果。調用 BeginInvoke 後可隨時調用 EndInvoke 方法;如果異步調用尚未完成,EndInvoke 將一直阻止調用線程,直到異步調用完成後才允許調用線程執行。EndInvoke 的參數包括您需要異步執行的方法的 out 和 ref 參數(在 Visual Basic 中爲 <Out> ByRef 和 ByRef)以及由 BeginInvoke 返回的 IAsyncResult。

接下來,MSDN提供了兩個例子:

 

第一個例子是:

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading;

 

namespace AsyncDemo

{

    class Program

    {

        public class AsyncDemo

        {

            // 這個方法將被異步調用

            public string TestMethod(int callDuration, out int threadId)

            {

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

                Thread.Sleep(callDuration);

                threadId = Thread.CurrentThread.ManagedThreadId;

                return String.Format("My call time was {0}.", callDuration.ToString());

            }

        }

        // 異步調用方法的委託,這個委託必須與TestMethod有同樣的簽名

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

 

 

        public static void Main()

        {

            // 異步調用方法將把它的thread id放在這裏

            int threadId;

 

            // 構建一個測試實例

            AsyncDemo ad = new AsyncDemo();

 

            // 構建委託

            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

 

            // 開始執行異步委託

            IAsyncResult result = caller.BeginInvoke(3000,

                out threadId, null, null);

 

            Thread.Sleep(0);

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

                Thread.CurrentThread.ManagedThreadId);

 

            // EndInvoke一直阻塞,一直到異步調用完成之後才返回

            // 並且取到了異步調用的返回值

            string returnValue = caller.EndInvoke(out threadId, result);

 

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",

                threadId, returnValue);

        }

 

    }

}

第二個例子是:

using System;

using System.Threading;

using System.Runtime.Remoting.Messaging;

using System.Collections.Generic;

using System.Text;

 

namespace DelegationTest

{

    // 構造一個異步調用方法來分解因式

    class PrimeFactorFinder

    {

        public static bool Factorize(

                    int number,

                    ref int primefactor1,

                    ref int primefactor2)

        {

            primefactor1 = 1;

            primefactor2 = number;

 

            // Factorize using a low-tech approach.

            for (int i = 2; i < number; i++)

            {

                if (0 == (number % i))

                {

                    primefactor1 = i;

                    primefactor2 = number / i;

                    break;

                }

            }

            if (1 == primefactor1)

                return false;

            else

                return true;

        }

 

    }

 

    // 構建一個異步委託來匹配異步調用方法

    public delegate bool AsyncFactorCaller(

             int number,

             ref int primefactor1,

             ref int primefactor2);

 

    public class DemonstrateAsyncPattern

    {

        // The waiter object used to keep the main application thread

        // from terminating before the callback method completes.

        ManualResetEvent waiter;

 

        // Define the method that receives a callback when the results are available.

        public void FactorizedResults(IAsyncResult result)

        {

            int factor1 = 0;

            int factor2 = 0;

 

            // Extract the delegate from the 

            // System.Runtime.Remoting.Messaging.AsyncResult.

            AsyncFactorCaller factorDelegate = (AsyncFactorCaller)((AsyncResult)result).AsyncDelegate;

            int number = (int)result.AsyncState;

            // Obtain the result.

            bool answer = factorDelegate.EndInvoke(ref factor1, ref factor2, result);

            // Output the results.

            Console.WriteLine("On CallBack: Factors of {0} : {1} {2} - {3}",

                number, factor1, factor2, answer);

            waiter.Set();

        }

 

        // 下面的方法演示了在異步調用中利用回調函數的方法(異步調用執行完成之後執行回調方法)

        public void FactorizeNumberUsingCallback()

        {

            AsyncFactorCaller factorDelegate = new AsyncFactorCaller(PrimeFactorFinder.Factorize);

            int number = 1000589023;

            int temp = 0;

            // Waiter will keep the main application thread from 

            // ending before the callback completes because

            // the main thread blocks until the waiter is signaled

            // in the callback.

            waiter = new ManualResetEvent(false);

 

            // Define the AsyncCallback delegate.

            AsyncCallback callBack = new AsyncCallback(this.FactorizedResults);

 

            // Asynchronously invoke the Factorize method.

            IAsyncResult result = factorDelegate.BeginInvoke(

                                 number,

                                 ref temp,

                                 ref temp,

                                 callBack,

                                 number);

 

            // Do some other useful work while 

            // waiting for the asynchronous operation to complete.

 

            // When no more work can be done, wait.

            waiter.WaitOne();

        }

 

        // 下面的方法演示了異步調用時使用輪詢方法而非回調方法(會比回調方法效率低一些)

        public void FactorizeNumberAndWait()

        {

            AsyncFactorCaller factorDelegate = new AsyncFactorCaller(PrimeFactorFinder.Factorize);

 

            int number = 1000589023;

            int temp = 0;

 

            // Asynchronously invoke the Factorize method.

            IAsyncResult result = factorDelegate.BeginInvoke(

                              number,

                              ref temp,

                              ref temp,

                              null,

                              null);

 

            while (!result.IsCompleted)

            {

                // Do any work you can do before waiting.

                result.AsyncWaitHandle.WaitOne(10000, false);

            }

            // The asynchronous operation has completed.

            int factor1 = 0;

            int factor2 = 0;

 

            // Obtain the result.

            bool answer = factorDelegate.EndInvoke(ref factor1, ref factor2, result);

 

            // Output the results.

            Console.WriteLine("Sequential : Factors of {0} : {1} {2} - {3}",

                              number, factor1, factor2, answer);

        }

 

        public static void Main()

        {

            DemonstrateAsyncPattern demonstrator = new DemonstrateAsyncPattern();

            demonstrator.FactorizeNumberUsingCallback();

            demonstrator.FactorizeNumberAndWait();

        }

    }

 

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章