zoukankan      html  css  js  c++  java
  • 异步编程模型

          使用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操作方法完成之后才可以继续,此时不建议使用异步(没啥意义)。

  • 相关阅读:
    列"xx"不在表Table中
    asp.net中自定义验证控件
    ASP.NET母版与内容页相对路径的问题
    html点小图看大图最快捷的方法
    ThinkCMF的跳转303 404等页面的方法
    关于ThinkCMF自带插件上传不了图片的解决方法
    js中百分比运算,大型数据会算错
    数据库价格汇总查询的方法
    信息资源5
    操作系统概论
  • 原文地址:https://www.cnblogs.com/kingge/p/3464675.html
Copyright © 2011-2022 走看看