异步、同步委托解析(一)

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

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

 

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

1  sealed   class  Decrement:MultiCastDelegate
2  {
3  }

 

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

ExpandedBlockStart.gif 完整的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委托的真实面貌之后,我们再来分析我们“从创建委托变量,到调用委托方法”的过程。

ExpandedBlockStart.gif 完整的委托应用实例
  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方法它是怎样阻塞的!!

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

ExpandedBlockStart.gif 修改后的委托应用实例
 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方法,这就是同步委托的调用过程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值