zoukankan      html  css  js  c++  java
  • 异步、同步委托解析(一)

        委托的定义想必大家都知道,它本质上是一个类,我们定义一个委托:

    1 delegate int Decrement(int x,int y);

    经过编译后,编译器自动生成一个从MultiCastDelegate继承下来的密封类:

    1 sealed class Decrement:MultiCastDelegate
    2 {
    3 }

    那么,Decrement这个类中应该包含哪些成员呢?经过分析,编译器给我们生成的完整的Decrement类应该是这样的:

    完整的Decrement类
    1 sealed class Decrement:MultiCastDelegate
    2 {
    3    public Decrement(object target,uint functionAddresss);//构造函数
    4    public int Invoke(int x,int y);//同步调用委托方法
    5    public IAsyncResult BeginInvoke(int x,int y,AsyncCallBack cb,object state);//异步调用委托方法
    6    public int EndInvoke(IAsyncResult ar);//异步结束委托方法的调用
    7    
    8 }

    我们知道,MultiCastDelegate类从Delegate类继承而来,他们都是abstract的,但是我们不能显示从他们派生新的类,只能由编译器做这个事情,查看MSDN,我们知道Delegate类有两个重要的公开属性:target 、method,其中target是Object类型的,method是System.Reflection.MethodInfo类型的(这个类型通常指一个方法,如果大家熟悉反射,就应该很清楚了),其中,method指该委托所绑定的方法,即创建委托变量时,传给构造函数的参数,这个参数通常是一个函数名,target指与method绑定的对象,如果我们这样创建一个委托变量:Decrement  d=new Decrement(obj.function);其中obj是一个对象,function是obj的成员函数,完了后,target就指obj对象了,method就指function函数了。

    好了,知道Decrement委托的真实面貌之后,我们再来分析我们“从创建委托变量,到调用委托方法”的过程。

    完整的委托应用实例
     1  using System;
     
    2  using System.Threading;//关于线程操作的命名空间(新加)
     3  namespace ConsoleApplication3
     
    4  {
     
    5        delegate int Decrement(int x,int y);//定义委托
     6        class Program
     
    7        {
     
    8            static void Main(string[] args)
     
    9            {
    10                                                                                                                     
    11                 Decrement MyDelegate=new Decrement(function);//创建委托变量,参数为function
    12                 int result=MyDelegate(10,8);//调用
    13                 
    14                 console.readline();
    15           }
    16   
    17           static int function(int x,int y)
    18           {
    19 
    20               return x-y;
    21           }
    22           
    23      }
    24   }

    以上是一个委托非常简单但普遍的运用方法,下面我们来分析一下该过程:

    1)、第一步,我们定义一个委托:delegate int Decrement(int x,int y);编译器为我们定义一个类:sealed class Decrement:MultiCastDelegate

    2)、第二步,我们创建一个委托变量:Decrement MyDelegate=new Decrement(function);相当于定义一个Decrement类的对象,同时调用它的构造函数,将function赋给method成员,target为null,当然,如果我们传给构造函数的是一个实例方法,也即这样传参:Decrement MyDelegate=new Decrement(obj.function)的,那么target就为obj;

    3)、第三步,创建完委托变量之后,我们就要运用它了:int result=MyDelegate(10,8),其实,当我们写下这一句代码时,实际调用的是MyDelegate.Invoke(10,8)这个成员函数,该方法是一个同步阻塞的,即直到function方法执行完之后,该方法才返回,同时返回function执行的结果。

    好了,三步刚好,我们要研究的是这个Invoke方法它是怎样阻塞的!!

    为了更好分析这个问题,我们再稍微改一下上面的那个委托应用实例:

    修改后的委托应用实例
     1  using System;
     2  using System.Threading;//关于线程操作的命名空间(新加)
     3   namespace ConsoleApplication3
     4   {
     5       delegate int Decrement(int x,int y);//定义委托
     6       class Program
     7       {
     8           static void Main(string[] args)
     9           {
    10                 Console.Write("Main方法所在线程ID:{0}\n",Thread.CurrentThread.ManagedThreadID);//输出Main方法所在线程ID,亦即主线程ID                                                                                                                     (新加)
    11  
    12                 Decrement MyDelegate=new Decrement(function);//创建委托变量,参数为function
    13                 int result=MyDelegate(10,8);//调用
    14                 
    15                 console.readline();
    16           }
    17   
    18           static int function(int x,int y)
    19           {
    20               Console.Write("function方法所在线程ID:{0}\n",Thread.CurrentThread.ManagedThreadID);//输出function方法所在线程ID(新加)         // Thread.Sleep(10000);
    21               return x-y;
    22           }
    23           
    24      }
    25   }

    在原来的基础上,我们分别在Main方法中输出该方法所在线程ID,function方法所在线程ID,运行之后,我们会发现,输出的两个ID相等,这说明,通过MyDelegate(10,8)这样调用委托方法时,系统并没有为我们开启一个新的线程来执行function方法,这就是同步委托的调用过程。

  • 相关阅读:
    聊聊算法——回溯算法
    Redis高级用法
    聊聊算法——BFS和DFS
    这就是Java代码生成器的制作流程
    Spring Boot 2 实战:常用读取配置的方式
    Spring Security 实战干货:图解Spring Security中的Servlet过滤器体系
    想做时间管理大师?你可以试试Mybatis Plus代码生成器
    Maven中央仓库正式成为Oracle官方JDBC驱动程序组件分发中心
    作为一个Java开发你用过Jib吗
    使用反应式关系数据库连接规范R2DBC操作MySQL数据库
  • 原文地址:https://www.cnblogs.com/xiaozhi_5638/p/1703916.html
Copyright © 2011-2022 走看看