异步编程模型

      使用IAsyncResult设计模式的异步操作是通过名为Begin操作名称和操作名称End的两个方法来实现的,这两个方法分别开始和结束异步操作。在调用Begin操作名称后,应用程序可以继续在调用线程上执行指令,同时异步操作在另一个线程上执行。每次调用Begin操作名称时,应用程序还应调用End操作名称来获取操作的结果。

      Begin 操作名称方法立即将控制权返回给调用线程。如果Begin操作名称方法引发异常,则会在开始异步操作之前引发异常。如果Begin操作名称方法引发异常,则意味着没有调用回调方法。

      End操作名称方法可结束异步操作。End操作名称方法的返回值与其同步副本的返回值类型相同,并且是特定于异步操作的。从应用程序的主线程调用End操作名称方法,阻止应用程序执行,直到操作完成之后再继续执行。

     

1 IAsyncResult ar=异步对象。BeginXXX(null,null);//控制权返回当前线程,继续执行
2 do something
3 异步对象。EndXXX(ar);//等待异步执行完毕,并处理完成继续后面操作
4 do otherthing


      由此可见End操作名称方法的正确实现应该使用返回的IAsyncResult对象的WaitHandle,或者使用IsCompleted轮询来等待异步执行完成并处理。为了验证,我使用Reflector查看了FileStream的EndRead方法。

 1 public override unsafe int EndRead(IAsyncResult asyncResult)
 2 {
 3     if (asyncResult == null)
 4     {
 5         throw new ArgumentNullException("asyncResult");
 6     }
 7     if (!this._isAsync)
 8     {
 9         return base.EndRead(asyncResult);
10     }
11     FileStreamAsyncResult result = asyncResult as FileStreamAsyncResult;
12     if ((result == null) || result._isWrite)
13     {
14         __Error.WrongAsyncResult();
15     }
16     if (1 == Interlocked.CompareExchange(ref result._EndXxxCalled, 1, 0))
17     {
18         __Error.EndReadCalledTwice();
19     }
20     WaitHandle handle = result._waitHandle;
21     if (handle != null)
22     {
23         try
24         {
25             handle.WaitOne();
26         }
27         finally
28         {
29             handle.Close();
30         }
31     }
32     NativeOverlapped* nativeOverlappedPtr = result._overlapped;
33     if (nativeOverlappedPtr != null)
34     {
35         Overlapped.Free(nativeOverlappedPtr);
36     }
37     if (result._errorCode != 0)
38     {
39         __Error.WinIOError(result._errorCode, Path.GetFileName(this._fileName));
40     }
41     return (result._numBytes + result._numBufferedBytes);
42 }

      在异步编程中使用End操作方法是必需的,即使End操作方法不返回任何值(可能为产生内存泄露,或者其它未知异常)。有一种简单的使用异步的编程方法必须谨慎,在Begin操作方法中使用AsyncCallback(调用End操作方法),这时虽然不需要再去调用End操作方法,代码运行也畅通无阻,但是有可能根本来不及执行AsyncCallback程序已经结束。

      另外如果在Begin操作方法和End操作方法之间如果无otherthing可做,或者剩下的工作必须等待End操作方法完成之后才可以继续,此时不建议使用异步(没啥意义)。

你可能感兴趣的:(编程)