异步、同步委托解析(一)
委托的定义想必大家都知道,它本质上是一个类,我们定义一个委托:
经过编译后,编译器自动生成一个从MultiCastDelegate继承下来的密封类:
2 {
3 }
那么,Decrement这个类中应该包含哪些成员呢?经过分析,编译器给我们生成的完整的Decrement类应该是这样的:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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委托的真实面貌之后,我们再来分析我们“从创建委托变量,到调用委托方法”的过程。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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方法它是怎样阻塞的!!
为了更好分析这个问题,我们再稍微改一下上面的那个委托应用实例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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方法,这就是同步委托的调用过程。
相关文章
- [linux]centos安装宝塔面板
- [javascript] vuejs的elementui配合iframe实现页面跳转
- [Go] 使用字面值方式初始化map
- [javascript] 基于elementui的后台界面开发
- [linux] linux宝塔面板安装GOFLY开源客服
- [docker] win10 docker桌面版镜像源
- [docker]解决:docker桌面版报错error during connect: This error may indicate that the docker daemon is not running
- [MySQL] 索引优化不只是用于面试
- [正则]正则表达式里面的?: ?! ?= ?<=
- 万字解读鸿蒙轻内核物理内存模块
- 上万规模数据湖如何在实验室测试
- 测试用例又双叒叕失败了,NLP帮你
- 云小课|大数据时代的隐私利器-GaussDB(DWS)数据脱敏
- ReplacingMergeTree:实现Clickhouse数据更新
- 华为云·核心伙伴开发者训练营——产业云专场在东莞松山湖圆满落幕
- 超全整理:程序员都在用什么工具?
- 顶会VLDB‘22论文解读:CAE-ENSEMBLE算法
- 拥抱时序数据库,构筑IoT时代下智慧康养数据存储底座
- CANN5.0黑科技解密 | 别眨眼!缩小隧道,让你的AI模型“身轻如燕”!
- 云小课|三大灵魂拷问GaussDB(DWS)数据落盘安全问题