zoukankan      html  css  js  c++  java
  • DotNet中异步编程(APM)的研究3代理与异步编程

    DotNet中异步编程(APM)的研究3
    代理与异步编程 (by zguosir/gshzheng)

    除了调用FCL中提供的异步方法外,.Net提供了一个非常有用的机制,使得任何一个方法都可以异步的调用,换言之,任何一个方法,都可以在单独的一个线程中异步的执行,执行完毕后将结果返回到调用线程。

    这个机制就是使用代理(delegate)。代理是C#中引入的相当聪明的语言元素。从现象上看,代理象C++中的类型安全函数指针,所以常用于事件定义或其它回掉机制。本质上,代理是个特殊的类,它封装了函数调用的功能。尤其是代理的异步调用功能,使程序开发的灵活性大大增加,也大量地屏蔽了多线程开发的难度。

    对任何方法,定义一个与其签名相同的代理,就可以通过代理的BeginInvoke()EndInvoke()来异步的调用。下面是一个演示了异步调用阶乘计算的例子。

    Example5

    public class UseDelegate

    {

         //要调用的方法

         public static int Factorial(int n)

         {

             if(n<=1) return 1;

             return n*Factorial(n-1);

         }

         public delegate int DelegateFactorial(int n);

         //异步调用

         public static void AsyncCall(int n)

         {

             DelegateFactorial dele=new DelegateFactorial(Factorial);

             dele.BeginInvoke(n,new AsyncCallback(cb_AsyncCall),null);

         }

         private static void cb_AsyncCall(IAsyncResult ar)

         {

             DelegateFactorial d=((ar as AsyncResult).AsyncDelegate) as DelegateFactorial;

             int i=d.EndInvoke(ar);

             Console.WriteLine(i);

         }

    }

     

    代理的BeginInvoke()的返回值是个AsyncResult对象,它实现了IAsyncResult接口,并且也记录了调用者代理实例dele,可以在回调函数中将ar强行转化为AsyncResult并取得AsyncDelegate后,通过它来调用EndInvoke()。注,其它的异步调用BeginOperation返回的对象不一定是AsyncResult类型,也未必有AsyncDelegate属性,需要借助于AsyncState参数等方式传入。

     

    代理本质上是个类,继承自MulticastDelegateMulticastDelegate 是一个特殊类。编译器和其他工具可以从此类派生,但是开发人员不能显式地从此类进行派生。 当定义了一个代理,

    public delegate int DelegateFactorial(int n);

    编译器将会自动生成一个等价的类

    public class DelegateFactorial : System.MulticastDelegate

    {

         public DelegateFactorial(Object target, Int32 methodPtr);

         public  virtual void Invoke(Int32 n);

         public virtual IAsyncResult BeginInvoke(Int32 n,AsyncCallback callback, Object state);

         public virtual int EndInvoke(IAsyncResult result);

    }

    其中,构造方法在实例化一个代理对象时由CLR调用,并自动传入当前对象到第一个参数(如果是静态方法则传入null);Invoke()方法就是直接调用时的同步方法,目前的vs.net编译器不允许直接调用此方法;BeginInvoke()EndInvoke()方法就是一对异步方法,它们的方法签名的格式与代理定义相一致:

    l           BeginInvoke()的后面固定为指定回调函数的两个参数;

    l           代理定义的所有参数(包括ref,out参数),将作为BeginInvoke前面的参数;

    l           EndInvoke()的最后一个参数,固定为IAsyncResult

    l           如果代理的参数列表中有ref,out参数,将作为EndInvoke前面的参数;

    l           EndInvoke()的返回值即为代理的返回值。

  • 相关阅读:
    phpcms后台进入地址(包含No permission resources错误)
    phpmyadmin上传大sql文件办法
    ubuntu彻底卸载mysql
    Hdoj 2602.Bone Collector 题解
    一篇看懂词向量
    Hdoj 1905.Pseudoprime numbers 题解
    The Python Challenge 谜题全解(持续更新)
    Hdoj 2289.Cup 题解
    Hdoj 2899.Strange fuction 题解
    Hdoj 2199.Can you solve this equation? 题解
  • 原文地址:https://www.cnblogs.com/zguosir/p/881219.html
Copyright © 2011-2022 走看看