现在的位置: 首页 > 综合 > 正文

.Net的异步机制(APM核心:IAsyncResult) – step 3

2013年02月18日 ⁄ 综合 ⁄ 共 5131字 ⁄ 字号 评论关闭

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

异步的核心: IAsyncResult

Asynchronous Programming Model

 

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

IAsyncResult接口

1public interface IAsyncResult
2    {
3        WaitHandle AsyncWaitHandle get; } //阻塞一个线程,直到一个或多个同步对象接收到信号
4        Boolean IsCompleted get; } //判读当前异步是否完成
5        Object AsyncState get; } //获取额外的参数值,请看上一篇文章的Code 4.3
6        Boolean CompletedSynchronously get; } //几乎没有使用
7    }

AsyncResult

 1    public class AsyncResult : IAsyncResult, IMessageSink
 2    {
 3        //IAsyncResult 的实现      
 4        public virtual WaitHandle AsyncWaitHandle get; }
 5        public virtual bool IsCompleted get; }
 6        public virtual object AsyncState get; }
 7        public virtual bool CompletedSynchronously get; }
 8
 9        // 其他一些重要的属性
10        public bool EndInvokeCalled getset; } //检验是否调用了EndInvoke()
11        public virtual object AsyncDelegate get; } //获取原始的委托对象,可查看上一篇文章中的Code 4.1/4.2/5
12    }

 

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

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

Code 1:

 1   class Program
 2    {
 3        static void Main(string[] args)
 4        {
 5            Console.WriteLine("[(#{1}){0}]:Asynchronous Start", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
 6
 7            AsyncTest test = new AsyncTest();
 8            MyThirdAsyncCode.AsyncTest.SalaryEventHandler del = test.YearlySalary;
 9            //使用回调函数
10            AsyncCallback callback = new AsyncCallback(OnSalaryCallback);
11            IAsyncResult ar = del.BeginInvoke(10000015100000, callback, 2000);
12
13            DoAntherJob();
14            Console.ReadLine(); // 让黑屏等待,不会直接关闭..
15        }

16
17        //开始其他工作.
18        static void DoAntherJob()
19        {
20            Thread.Sleep(1000);//需要1秒才能完成这个工作,注1
21            Console.WriteLine("[(#{1}){0}]:Do Another Job", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
22        }

23
24        static void OnSalaryCallback(IAsyncResult asyncResult)
25        {
26            //通过AsyncState 获取额外的参数.
27            decimal para = (int)asyncResult.AsyncState;
28
29            //通过AsyncDelegate 获取原始的委托对象
30            AsyncResult obj = (AsyncResult)asyncResult;
31            MyThirdAsyncCode.AsyncTest.SalaryEventHandler del = 
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
32
33            if (asyncResult.IsCompleted)// 判读是否已经调用完成
34                Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
35
36            decimal val = del.EndInvoke(asyncResult);
37
38            Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val + para, Thread.CurrentThread.ManagedThreadId);
39        }

40    }

41
42    public class AsyncTest
43    {
44        public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus); // 对应YearlySalary方法
45        public decimal YearlySalary(decimal salary, int monthCount, decimal bonus)
46        {
47            //模拟耗时/复杂的逻辑计算.
48            Thread.Sleep(3000);//等待3秒,注2
49            return salary * monthCount + bonus;
50        }

51    }



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();


1.1

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

2, WaitAll

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

Code 1.2

 1    class Program
 2    {
 3        static void Main(string[] args)
 4        {
 5            Console.WriteLine("[(#{1}){0}]:Asynchronous Start", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
 6
 7            AsyncTest test = new AsyncTest();
 8            MyThirdAsyncCode.AsyncTest.SalaryEventHandler del = test.YearlySalary;
 9            MyThirdAsyncCode.AsyncTest.AsyncEventHandler asy = test.Hello;
10
11            IAsyncResult salayAsyc = del.BeginInvoke(10000015100000, OnSalaryCallback, null);
12            IAsyncResult helloAsyc = asy.BeginInvoke("Hello Andy", OnHelloCallback, null);
13            //把所有异步的句柄保存到WaitHandle 对象中
14            WaitHandle[] handles = { salayAsyc.AsyncWaitHandle, helloAsyc.AsyncWaitHandle };
15            //阻碍当前线程,直到所有异步调用结束.
16            WaitHandle.WaitAll(handles);
17
18            //开始其他工作.
19            DoAntherJob();
20            Console.ReadLine(); // 让黑屏等待,不会直接关闭..
21        }

22        static void DoAntherJob()
23        {
24            Thread.Sleep(1000);//需要1秒才能完成这个工作,注1
25            Console.WriteLine("[(#{1}){0}]:Do Another Job", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
26        }

27        static void OnSalaryCallback(IAsyncResult asyncResult)
28        {
29            //通过AsyncDelegate 获取原始的委托对象
30<

抱歉!评论已关闭.