• 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()的返回值即为代理的返回值。

  • 相关阅读:
    关于Maven项目build时出现No compiler is provided in this environment的处理
    freemaker的函数使用
    FTP在docker容器中上传失败解决,改为被动模式
    linux重定向及nohup不输出的方法
    手动抠下的wordpress登录页面样式
    使用后端生成图片验证码流文件(不推荐)
    部署到docker容器后图片验证码显示不出来
    Linux修改profile文件改错了,恢复的方法
    DotNETCore 学习笔记 异常处理
    DotNETCore 学习笔记 路由
  • 原文地址:https://www.cnblogs.com/zguosir/p/881219.html
Copyright © 2020-2023  润新知