通过委托来实现异步 Delegate的BeginInvoke和EndInvoke
什么是.net的异步机制呢?
解释这个话题之前,先让我们来看看同步执行的程序
https://github.com/chucklu/Test/blob/master/DotNet4.5开发指南/并行处理和并发/异步编程模式/APM/SyncProcedure/Program.cs
- static class SyncTest
- {
- public static void Method()
- {
- Console.WriteLine("SyncTest类中的Method()函数的线程ID是{0}", Thread.CurrentThread.ManagedThreadId);//Environment.CurrentManagedThreadId
- if (Thread.CurrentThread.IsThreadPoolThread)//判断当前线程是否托管在线程池上
- {
- Console.WriteLine("SyncTest类中的Method()函数的线程托管于线程池");
- }
- else
- {
- Console.WriteLine("SyncTest类中的Method()函数的线程没有托管在线程池上");
- }
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("Program类中的Main()函数的线程ID是{0}", Thread.CurrentThread.ManagedThreadId);//Environment.CurrentManagedThreadId
- if (Thread.CurrentThread.IsThreadPoolThread)//判断当前线程是否托管在线程池上
- {
- Console.WriteLine("Program类中的Main()函数的线程托管于线程池");
- }
- else
- {
- Console.WriteLine("Program类中的Main()函数的线程没有托管在线程池上");
- }
- Console.WriteLine();
- SyncTest.Method();//调用静态类的静态方法
- Console.Read();//阻塞,确保能看到上面的打印信息
- }
- }
执行结果如下图所示
从图中可以看出,在主函数中调用另外一个类SyncTest的方法,
进入方法Method的时候,此方法还是和Main函数在同一个线程上执行的
并且该线程不是托管在线程池上的线程
接下来写一个通过委托,进行异步执行的方法
https://github.com/chucklu/Test/blob/master/DotNet4.5开发指南/并行处理和并发/异步编程模式/APM/AsyncProcedure/Program.cs
不要尝试去查看BeginInvoke和EndInvoke的实现,右键,转到定义,是看不到的。这两个方法是CLR为委托类型添加的
- /// <summary>
- /// 声明一个委托 委托的名字是AsyncHandler
- /// </summary>
- /// <param name="name"></param>
- public delegate void AsyncHandler();//委托的声明方式类似于函数,只是比函数多了一个delegate关键字
- static class AsyncTest
- {
- public static void Method()
- {
- Console.WriteLine("AsyncTest类中的Method()函数的线程ID是{0}", Thread.CurrentThread.ManagedThreadId);//Environment.CurrentManagedThreadId
- if (Thread.CurrentThread.IsThreadPoolThread)//判断当前线程是否托管在线程池上
- {
- Console.WriteLine("AsyncTest类中的Method()函数的线程托管于线程池");
- }
- else
- {
- Console.WriteLine("AsyncTest类中的Method()函数的线程没有托管在线程池上");
- }
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("Program类中的Main()函数的线程ID是{0}", Thread.CurrentThread.ManagedThreadId);//Environment.CurrentManagedThreadId
- if (Thread.CurrentThread.IsThreadPoolThread)//判断当前线程是否托管在线程池上
- {
- Console.WriteLine("Program类中的Main()函数的线程托管于线程池");
- }
- else
- {
- Console.WriteLine("Program类中的Main()函数的线程没有托管在线程池上");
- }
- Console.WriteLine();
- //把Method 方法分配给委托对象
- AsyncHandler async = AsyncTest.Method; //
- //发起一个异步调用的方法,返回IAsyncResult 对象
- IAsyncResult result = async.BeginInvoke(null,null);
- //这里会阻碍线程,直到方法执行完毕
- async.EndInvoke(result);
- Console.Read();
- }
- }
运行结果如下图所示
从上图可以看出,委托的BeginInvoke,是新开了一个线程运行方法,并且该线程是托管在线程池上的
上面两个代码的示例,区别在于,第二个使用的是委托的BeginInvoke方法
通过反编译工具,我们可以查看委托具体做了什么,一般.net Reflector不错,最近新发现一个叫ILSpy的,开源的反编译工具
https://github.com/icsharpcode/ILSpy 官网的.sln是VS2013的,如果不想自己编译的,也可以去官网下载编译好的exe程序
官网链接是http://ilspy.net/ 右上角有一个Download Binaries,点击下载就可以了
接下来上图,反编译的结果
从上图可以发现AsyncHandler委托的结构如下
- public extern AsyncHandler(object @object, IntPtr method);
- public virtual extern IAsyncResult BeginInvoke(AsyncCallback callback, object @object);
- public virtual extern void EndInvoke(IAsyncResult result);
- public virtual extern void Invoke();
而且可以发现继承层次,AsyncHandler从MulticastDelegate继承,再上层是Delegate类(注意,大写的Delegate表示的是类,而不是delegate关键字)
去msdn上找了相关信息
Delegate类
- public abstract class Delegate : ICloneable,ISerializable
- The Delegate class is the base class for delegate types.
- Delegate类是delegate类型的基类
- However, only the system and compilers can derive explicitly from the Delegate class or from the MulticastDelegate class.
- 然后只有系统和编译器才可以从Delegate类或者MulticastDelegate类进行派生
- It is also not permissible to derive a new type from a delegate type.
- 从委托类型派生一个新类型也是不允许的
- The Delegate class is not considered a delegate type; it is a class used to derive delegate types.
- Delegate类并不是委托类型,它只是一个用于派生委托类型的类。
- Most languages implement a delegate keyword, and compilers for those languages are able to derive from the MulticastDelegate class; therefore, users should use the delegate keyword provided by the language.
- 大多数语言实现了delegate关键字,并且这些语言的编译器是能够从MulticastDelegate类进行派生的,所以,开发者们应该使用开发语言所提供的delegate关键字
- The common language runtime provides an Invoke method for each delegate type, with the same signature as the delegate.
- CLR为每一个委托类型提供了一个Invoke方法,并且该方法和delegate拥有相同的签名
- The common language runtime provides each delegate type with BeginInvoke and EndInvoke methods, to enable asynchronous invocation of the delegate.
- CLR为每一个委托类型提供了BeginInvoke和EndInvoke方法,来确保委托的异步调用
MulticastDelegate类
- public abstract class MulticastDelegate : Delegate
- MulticastDelegate is a special class. Compilers and other tools can derive from this class, but you cannot derive from it explicitly. The same is true of the Delegate class.
- 多播委托是一个特殊的类。编译器或者其他工具,可以从从这个类派生,但是你不能显式地从这个类派生。同样的规则适用于Delegate类。
- In addition to the methods that delegate types inherit from MulticastDelegate, the common language runtime provides two special methods: BeginInvoke and EndInvoke.
- delegate关键字声明的委托,不但继承了多播委托的方法,并且CLR还提供了两个特殊的方法BeginInvoke和EndInvoke
更多关于BeginInvoke和EndInvoke的信息可以参见此链接[使用异步方式调用同步方法]http://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.110).aspx
使用委托进行异步编程http://msdn.microsoft.com/zh-cn/library/22t547yb(v=vs.110).aspx
转载自http://www.cnblogs.com/AndyHuang/archive/2008/12/24/1361267.html (有自己的修改和理解)
通过委托来实现异步 Delegate的BeginInvoke和EndInvoke的更多相关文章
- 用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程
让我们首先了解下什么时候用到C#异步调用: .NET Framework 允许您C#异步调用任何方法.定义与您需要调用的方法具有相同签名的委托:公共语言运行库将自动为该委托定义具有适当签名的Begin ...
- 【C#】用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程
让我们首先了解下什么时候用到C#异步调用: .NET Framework 允许您C#异步调用任何方法.定义与您需要调用的方法具有相同签名的委托:公共语言运行库将自动为该委托定义具有适当签名的Begin ...
- delegate 中的BeginInvoke和EndInvoke方法
开发语言:C#3.0 IDE:Visual Studio 2008 一.C#线程概述 在操作系统中一个进程至少要包含一个线程,然后,在某些时候需要在同一个进程中同时执行多项任务,或是为了提供程序的性能 ...
- 读书笔记 C#委托的BeginInvoke、EndInvoke之浅析
c#中有一种类型叫委托,它是一种引用类型.可以引用静态与非静态的方法,且这些方法的参数列表和返回值类型必须与所声明的委托一致. 委托引用的方法可以通过BeginInvoke和EndInvoke来异步进 ...
- C#--委托的同步,异步,回调函数
原文地址 同步调用 委托的Invoke方法用来进行同步调用.同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行. using System; using System. ...
- c#委托中的同步和异步方法即BeginInvoke和EndInvoke
学习多线程之前我们先了解一下电脑的一些概念,比如进程,线程,这个参考https://www.cnblogs.com/loverwangshan/p/10409755.html 这篇文章.今天我们接着来 ...
- C#线程系列讲座(1):BeginInvoke和EndInvoke方法
一.C#线程概述 在操作系统中一个进程至少要包含一个线程,然后,在某些时候需要在同一个进程中同时执行多项任务,或是为了提供程序的性能,将要执行的任务分解成多个子任务执行.这就需要在同一个进程中开启多个 ...
- C#线程应用实例(part1) 之 BeginInvoke和EndInvoke
最近这个公司是做 winfrom 开发的 , 这段时间就好好的学学WCF , 公司框架什么的自己去琢磨! 这里主要写一些 winfrom 中 用到的一些陌生 技术 1.BeginInvoke 以前B ...
- 转:C#线程系列讲座(1) BeginInvoke和EndInvoke方法
转载自:http://www.cnblogs.com/levin9/articles/2319248.html 开发语言:C#3.0IDE:Visual Studio 2008本系列教程主要包括如下内 ...
随机推荐
- jquery类似方法的比较(二)
(1)append()&appendTo()&prepend()$prependTo() (2)after()&before()&insertAfter()&i ...
- JavaScript三(对象思想)
JavaScript并不是面向对象的程序设计语言,但它是基于对象的.JavaScript中的每个函数都可用于创建对象,返回的对象既是该对象的实例,也是object的实例 . 一.对象与关联数组 Jav ...
- SVN跨版本库迁移目录并保留提交日志
现在有一份代码code在版本库reposA/dirB/下,现在想把它移动到reposB/dirAA/下,本来打算交给SA做,没想到SA似乎 也不太懂的样子.于是,自己在VPS搭建了一个svnserve ...
- 转!!CMPP 网关错误码说明
http://www.163duanxin.com/msg/1753.htm CMPP错误码说明 与中国移动代码的对应关系. MI::zzzzSMSC返回状态报告的状态值为EXPIREDMJ:zz ...
- scrapy-redis分布式爬虫
简介 Scrapy-Redis则是一个基于Redis的Scrapy分布式组件.它利用Redis对用于爬取的请求(Requests)进行存储和调度(Schedule), 并对爬取产生的项目(items) ...
- Jquery EasyUI插件
属性 属性是定义在 jQuery.fn.{plugin}.defaults.比如,dialog 的属性是定义在 jQuery.fn.dialog.defaults. 事件 事件(回调函数)也是定义在 ...
- web项目读取classpath路径下面的文件
首先分两大类按web容器分类 一种是普通的web项目,像用Tomcat容器,特点是压缩包随着容器的启动会解压缩成一个文件夹,项目访问的时候,实际是去访问文件夹,而不是jar或者war包. 这种的无论你 ...
- 远程终端登录软件MobaXterm
提到SSH.Telnet等远程终端登录,我相信很多人想到的都是PuTTY[注A]. PuTTY足够成熟.小巧.专注核心任务,并且对编码等常见坑的处理并不缺乏,这其实都是优点.但PuTTY在额外功能上就 ...
- Smarty小结提纲
Smarty:模板技术 实现功能:前后分离. 原理:主要通过Smarty核心类实现,调用display方法,将模板文件读取,用正则进行替换,替换完保存到临时文件,将临时文件加载到当前页面. 配置文件( ...
- 关于Serializable的一个形象的例子
一.知识预备 根据使用Serializable的使用场景,可以发现所涉及的场景都是跨进程的,就是要做的事情不是在一个java进程中完成的,我们都知道java进程是基于jvm跑起来的,而每一个被创建出来 ...