在上一篇文章(什么是.Net的异步机制(Invoke,BeginInvoke,EndInvoke) - step 2 ), 我们已经简单介绍了异步的调用方式, 下面我们来看看异步的核心.

异步的核心: IAsyncResult

Asynchronous Programming Model

 

整个异步调用过程中都是围绕IAsyncResult来进行的,大家可以看看上篇文章的例子,BeginXXX 返回这个对象,EndXXX接收这个对象来结束当前异步对象,下面我们来看看IAsyncResult 接口成员/和实现此接口的AsyncResult成员(其中有些在上篇中已经涉及到)

IAsyncResult接口

1什么是.Net的异步机制(APM核心:IAsyncResult) - step 3public interface IAsyncResult
2    }

AsyncResult

 1什么是.Net的异步机制(APM核心:IAsyncResult) - step 3    public class AsyncResult : IAsyncResult, IMessageSink
 2    }

 

注意:基本上都是只读属性

下面我们来看看异步的执行顺序,并回顾下 IAsyncResult 下各个属性的应用,如果还是不熟悉请看前2篇文章.

Code 1:

 1什么是.Net的异步机制(APM核心:IAsyncResult) - step 3   class Program
 2
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
32什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
33什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            if (asyncResult.IsCompleted)// 判读是否已经调用完成
34什么是.Net的异步机制(APM核心:IAsyncResult) - step 3                Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
35什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
36什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            decimal val = del.EndInvoke(asyncResult);
37什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
38什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val + para, Thread.CurrentThread.ManagedThreadId);
39什么是.Net的异步机制(APM核心:IAsyncResult) - step 3        }
40什么是.Net的异步机制(APM核心:IAsyncResult) - step 3    }
41什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
42什么是.Net的异步机制(APM核心:IAsyncResult) - step 3    public class AsyncTest
43    }


什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
1

我们看到DoAntherJob 比异步YearlySalary2,看代码中(1)(2),两个线程的执行结果

接下来,我们说说AsyncWaitHandle 属性. 他返回WaitHandle对象(System.Threading.WaitHandle), 他有3个重要的方法. WaitOne / WaitAny / WaitAll ,我们先来说下WaitOne,Code1代码基础上只是增加了下面红色部分.

1,WaitOne

Code 1.1

IAsyncResult ar = del.BeginInvoke(100000, 15, 100000, callback, 2000);
//
阻碍当前线程,直到异步调用结束.
ar.AsyncWaitHandle.WaitOne();

//
开始其他工作.
DoAntherJob();

什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
1.1

执行输出,对比图1我们可以看到执行的次序不一样了(看时间),调用WaitOne,会阻碍当前线程,直到异步完成,才释放当前的线程, WaitOne 提供了时间的重载版本WaitOne(int millisecondsTimeout)/ WaitOne(TimeSpan timeout);来判断阻碍的时间.无参的版本是无限等待的(直到异步调用结束)

2, WaitAll

我们在Code1的代码基础上加上Hello的异步调用(使Main提供多个异步调用),注意红色部分.

Code 1.2

 1什么是.Net的异步机制(APM核心:IAsyncResult) - step 3    class Program
 2
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
32什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
33什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            if (asyncResult.IsCompleted)// 判读是否已经调用完成
34什么是.Net的异步机制(APM核心:IAsyncResult) - step 3                Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
35什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
36什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            decimal val = del.EndInvoke(asyncResult);
37什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val, Thread.CurrentThread.ManagedThreadId);
38什么是.Net的异步机制(APM核心:IAsyncResult) - step 3        }
39什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
40什么是.Net的异步机制(APM核心:IAsyncResult) - step 3        static void OnHelloCallback(IAsyncResult asyncResult)
41
(MyThirdAsyncCode.AsyncTest.AsyncEventHandler)obj.AsyncDelegate;
45什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
46什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            if (asyncResult.IsCompleted)// 判读是否已经调用完成
47什么是.Net的异步机制(APM核心:IAsyncResult) - step 3                Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
48什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
49什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            string val = del.EndInvoke(asyncResult);
50什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val, Thread.CurrentThread.ManagedThreadId);
51什么是.Net的异步机制(APM核心:IAsyncResult) - step 3        }
52什么是.Net的异步机制(APM核心:IAsyncResult) - step 3    }
53什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
54什么是.Net的异步机制(APM核心:IAsyncResult) - step 3    public class AsyncTest
55    }


什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
1.2

从图1.2中可以看出,WaitAll会阻碍当前线程(主线程#10),等待所有异步的对象都执行完毕(耗时最长的异步),才释放当前的线程,WaitAll/WaitAny的重载版本和WaitOne一样.

3, WaitAny

WaitAll 基本上是一样的.我们可以使用 WaitAny 来指定某个/某几个委托先等待,修改Code1.2红色部分,使用WaitAny.

Code1.3
//
salayAsyc异步的句柄保存到WaitHandle 对象中
WaitHandle
[] handles = { salayAsyc.AsyncWaitHandle };
//
阻碍当前线程,直到所有异步调用结束.
WaitHandle
.WaitAny(handles);

什么是.Net的异步机制(APM核心:IAsyncResult) - step 3

1.3

我们阻碍了DoAntherJob(#10)线程,直到Salary异步调用计算完成.同样我们可以巧用这三个方法来改变我们方法执行的顺序.


释放资源

Code2

1什么是.Net的异步机制(APM核心:IAsyncResult) - step 3static void OnSalaryCallback(IAsyncResult asyncResult)
2
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
6什么是.Net的异步机制(APM核心:IAsyncResult) - step 3
7什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            decimal val = del.EndInvoke(asyncResult);
8什么是.Net的异步机制(APM核心:IAsyncResult) - step 3            asyncResult.AsyncWaitHandle.Close();//显示的释放资源
9什么是.Net的异步机制(APM核心:IAsyncResult) - step 3        }


当开始调用BeginXXX,就会创建一个新的AsyncResult对象.这个对象会构造一个WaitHandle句柄(通过AsyncWaitHandle访问),当我们EndXXX,并不会马上关闭这个句柄,而是等待垃圾收集器来关闭,这时候我们最后在调用EndXXX完成后,显示的关闭这个句柄.

 

说到这里,我们基本上把异步方法都解释一遍,下面我们来看看重构的异步对象,我们也可以细细体会异步对象的内部执行代码..下面Code3.1/3.2/3.3代码来自Jeffery Richard大师的Power Threading类库,具体可查看http://msdn.microsoft.com/en-us/magazine/cc163467.aspx

 

重构的异步对象

 

1,构造一个内部无参的AsyncResultNoResult对象,继承IAsyncResult接口(保留原创的注释)

Code3.1

  1什么是.Net的异步机制(APM核心:IAsyncResult) - step 3 internal class AsyncResultNoResult : IAsyncResult
  2    }

2,继承AsyncResultNoResult对象,并且为他提供返回值和泛型的访问

Code3.2

 1什么是.Net的异步机制(APM核心:IAsyncResult) - step 3internal class AsyncResult<TResult> : AsyncResultNoResult
 2    }


3,模拟长时间的异步工作

Code3.3

 1什么是.Net的异步机制(APM核心:IAsyncResult) - step 3internal sealed class LongTask
 2    }


来自
Jeffrey Richter大师更多更详细的异步操作方法, 请查看http://www.wintellect.com/PowerThreading.aspx,对于一些朋友可能看不懂Code3.1-3.3代码(其实没什么所谓的),因为涉及到过多的线程知识,这里出于让你获得更多的更深层次的(异步)认识为目的,才提供上面代码,在以后的文章会再次探讨.

 

下一篇章中,我们来看看微软提供有异步调用的类是如何调用的,并从中我会给出些真实应用环境中的一些小技巧,让你编写的代码更健壮更完善.

以上有word 文档直接粘贴,排版可能不太看,你可以通过下面来下载相应的代码/文档

1,文档

2,代码(VS2008开发,.Net Framework 2.0(C Sharp)编写)

文章为原创,如果需要引用,请保留原地址. 有什么问题/错误的地方请联系 fox7805034 (at) hotmail.com

相关文章: