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();

        }

    }

 

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值