惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
IT之家
IT之家
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园_首页
Blog — PlanetScale
Blog — PlanetScale
V
Visual Studio Blog
云风的 BLOG
云风的 BLOG
MyScale Blog
MyScale Blog
阮一峰的网络日志
阮一峰的网络日志
Stack Overflow Blog
Stack Overflow Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
GbyAI
GbyAI
V
V2EX
N
Netflix TechBlog - Medium
Vercel News
Vercel News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Blog of Author Tim Ferriss
量子位
博客园 - Franky
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
月光博客
月光博客
F
Fortinet All Blogs

博客园 - Kevin-moon

在IE中本地浏览与服务器浏览同一Html后,出现了奇异的结果 如何避免JQuery Dialog的内存泄露 JQuery另类视角-动态执行脚本的BUG JQuery另类视角-动态扩展对象 - Kevin-moon - 博客园 如何重构代码-简单、灵活的实现对象复制 如何重构代码-重构计划 如何重构代码-思路和方法 谈谈多线程的思维方式 简单的数据移动算法(C#) [ASP.NET MVC]-理解Routing 笑死人的十项大奖 [Windbg基础]-了解Symbols 深入线程,实现自定义的SynchronizationContext 重温ASP.NET的配置信息(简单、常用) 奇妙的SynchronizationContext 线程之间的通讯---SynchronizationContext "对象"到"山寨对象"的完整转换 我真的就只能在远方看你吗?!!! "测试驱动开发(TDD)" 动态进行"自定义公式"计算
深入APM,实现自己的APM
Kevin-moon · 2009-02-23 · via 博客园 - Kevin-moon

     APM(Asynchronous Programming Model),异步编程模型。
     大家对这个应该不会陌生,甚至太过于熟悉了吧!因为在太多的地方看到过它,对于应用上也许更没的说了!呵呵。
     Control:BeginInvoke、EndInvoke
     Stream:BeginWrite、EndWrite
     ......
     上面这些都是FCL已经提供的可以使用APM的类,不过可能在一些特定的情况下:

1、构建和一些硬件(FCL没有提供支持的)直接交互的类。
2、BeginXXX、EndXXX这些都不是相同的名称,希望让调用者使用起来更加简单,对于这些现有的异步类进行下抽象。
3、在自定义的类上执行某些方法也许需要很多的时间,这些希望对这些方法进行异步处理,所以也加上APM这种方式。
4、一些Win32的函数(Win32注册表、日志...)目前只提供了同步处理,所以当使用这些的时候,希望对这些函数做些封装,加上异步支持。
............
     
     相信大家现在都明白为什么要自己的APM了吧!OK,那就让我们开始吧!


APM的核心(IAsyncResult)
     IAsyncResult接口是APM机制的核心:

public interface IAsyncResult {
   WaitHandle AsyncWaitHandle { 
get; } // For Wait-Until-Done technique
   Boolean    IsCompleted     { get; } // For Polling technique
   Object     AsyncState      { get; } // For Callback technique
   Boolean    CompletedSynchronously { get; } // Almost never used
}

     

当任何一个BeginXXX方法被调用的时候,都会返回一个继承于该接口的对象。该对象可以用来监视异步动作的执行,例如,当调用BeginXXX后,我们可以通过该对象的属性判断异步动作是否完成,同时如果异步执行的时候有异常,那么就会将异常信息传给EndXXX方法,EndXXX方法等待异步动作执行完成后,将异常抛出。
     AsyncResultNoResult类继承于IAsyncResult接口,该类用于无特殊返回值的异步动作(执行成功或失败),例如stream的BeginWrite、EndWrite。
     public override void EndWrite(IAsyncResult asyncResult)AsyncResultNoResult类:

Code

     详细分析下,AsyncResultNoResult的构造函数接受两个参数(异步委托和执行参数),这两个参数被保存到私有属性中。定义了m_CompletedState字段,用于实现IAsyncResult的 IsCompleted和CompletedSynchronously属性,也定义了m_AsyncWaitHandle字段用于实现IAsyncResulte的AsyncWaitHandle,而且还有一个异常字段m_exception,当成功执行的时候,把该值设为null,失败的时候,将被设置导致失败的异常。
     还有一个重要的属性(m_AsyncWaitHandle),我们在EndInvoke方法可以看到m_AsyncWaitHandle.WaitOne()这行代码,执行到这里的时候,m_AsyncWaitHandle如果没有被释放的话,程序将一直等待,释放的程序在SetAsCompleted方法中m_AsyncWaitHandle.Set()。

AsyncResult类:

Code

     看下代码应该很清晰了,该类继承与AsyncResultNoResult类,额外加了m_result属性,用于返回值。

利用自定义的IAsyncResult实现APM


     现在我们已经知道如何定义IAsyncResult,那么就开始展示如何使用AsyncResult<TResult>和AsyncResultNoResult。
     定义一个类:LongTask,该类对一些很耗时的方法进行异步处理,并且当执行完成的时候返回一个时间数据。

Code

     当调用BeginDoTask的时候,先实例化一个AsyncResult对象,然后把DoTaskHelper方法加到线程池上,而DoTaskHelper方法只是对执行动作进行了封装,如果该方法成功执行,则返回时间数据,如果出现异常,则设定异常信息,用于EndDoTask的时候抛出。测试和性能
1、测试LongTask

Code

执行结果如下:

2、比较自定义APM和delegate之间的性能

Code

执行结果如下:

     从结果上看,既然自定义的APM性能要比FCL的APM好点,其实在这里大家仔细看下就可以清楚:
     区别就在于ManualResetEvent,FCL的APM是在创建IAsyncResult对象的同时,也创建了ManualResetEvent。而AsyncResultNoResult中,可以看下面的代码,只有在真正需要用到ManualResetEvent的时候,才去创建,一般不实例化。有个注意的地方:ManualResetEvent是内核对象,而创建或使用一个内核对象都是很耗资源的,所以只有当真正需要的时候才去使用。

public WaitHandle AsyncWaitHandle
   {
      
get
      {
         
if (m_AsyncWaitHandle == null)
         {
            Boolean done 
= IsCompleted;
            ManualResetEvent mre 
= new ManualResetEvent(done);
            
if (Interlocked.CompareExchange(ref m_AsyncWaitHandle, 
               mre, 
null!= null)
            {
               mre.Close();
            }
            
else
            {
               
if (!done && IsCompleted)
               {
                  m_AsyncWaitHandle.Set();
               }
            }
         }
         
return m_AsyncWaitHandle;
      }

参考Jeffrey Richter的

http://msdn.microsoft.com/en-us/magazine/cc163467.aspx