近期项目中使用了不少异步操作,关于“异步”做个总结。总结的内容大部分都来自于MSDN,还有一些自己的心得。

关于“异步”的使用可分为:使用层面和类库设计层面,细分如下:

一、使用异步方式调用同步方法(使用层面)。

二、使用 IAsyncResult 调用异步方法(使用层面)。

三、基于 IAsyncResult 的异步设计模式(设计层面)。

四、基于事件的异步模式(设计层面)。

关于上述异步编程的几个方面,下面分别做以详述。

一、使用异步方式调用同步方法(使用层面)

.NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义 BeginInvoke 和 EndInvoke 方法。BeginInvoke 方法可启动异步调用,EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。

该调用方式是使用委托进行异步调用,其实质是:调用“BeginInvoke”方法,公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行,该目标方法是在线程池线程运行的。

在异步调用启动后,在等待异步调用结果的时候,可以进行以下四种方法。

·                     进行某些操作,然后调用 EndInvoke 一直阻止到调用完成。

  1. using System;
  2. using System.Threading;
  3. namespace Examples.AdvancedProgramming.AsynchronousOperations
  4. {
  5. public class AsyncMain
  6. {
  7. public static void Main()
  8. {
  9. // The asynchronous method puts the thread id here.
  10. int threadId;
  11. // Create an instance of the test class.
  12. AsyncDemo ad = new AsyncDemo();
  13. // Create the delegate.
  14. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
  15. // Initiate the asychronous call.
  16. IAsyncResult result = caller.BeginInvoke(3000,
  17. out threadId, null, null);
  18. Thread.Sleep(0);
  19. Console.WriteLine("Main thread {0} does some work.",
  20. Thread.CurrentThread.ManagedThreadId);
  21. // 调用此方法将会一直等待异步操作完成,并阻塞当前线程。
  22. string returnValue = caller.EndInvoke(out threadId, result);
  23. Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
  24. threadId, returnValue);
  25. }
  26. }
  27. }

·                     进行某些操作,然后使用
IAsyncResult..::.AsyncWaitHandle 属性获取 WaitHandle,使用它的 WaitOne
方法(该方法可以设置一个超时时间)一直阻止执行直到发出 WaitHandle 信号,然后调用 EndInvoke。

  1. using System;
  2. using System.Threading;
  3. namespace Examples.AdvancedProgramming.AsynchronousOperations
  4. {
  5. public class AsyncMain
  6. {
  7. static void Main()
  8. {
  9. // The asynchronous method puts the thread id here.
  10. int threadId;
  11. // Create an instance of the test class.
  12. AsyncDemo ad = new AsyncDemo();
  13. // Create the delegate.
  14. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
  15. // Initiate the asychronous call.
  16. IAsyncResult result = caller.BeginInvoke(3000,
  17. out threadId, null, null);
  18. Thread.Sleep(0);
  19. Console.WriteLine("Main thread {0} does some work.",
  20. Thread.CurrentThread.ManagedThreadId);
  21. // 调用此方法将会一直等待异步操作完成,并阻塞当前线程。
  22. result.AsyncWaitHandle.WaitOne();
  23. // Perform additional processing here.
  24. // Call EndInvoke to retrieve the results.
  25. string returnValue = caller.EndInvoke(out threadId, result);
  26. Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
  27. threadId, returnValue);
  28. }
  29. }
  30. }

·                     进行某些操作,然后轮询由 BeginInvoke 返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。

  1. using System;
  2. using System.Threading;
  3. namespace Examples.AdvancedProgramming.AsynchronousOperations
  4. {
  5. public class AsyncMain
  6. {
  7. static void Main()
  8. {
  9. // The asynchronous method puts the thread id here.
  10. int threadId;
  11. // Create an instance of the test class.
  12. AsyncDemo ad = new AsyncDemo();
  13. // Create the delegate.
  14. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
  15. // Initiate the asychronous call.
  16. IAsyncResult result = caller.BeginInvoke(3000,
  17. out threadId, null, null);
  18. // 等待结果返回
  19. while (result.IsCompleted == false)
  20. {
  21. Thread.Sleep(10);
  22. }
  23. // Call EndInvoke to retrieve the results.
  24. string returnValue = caller.EndInvoke(out threadId, result);
  25. Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
  26. threadId, returnValue);
  27. }
  28. }
  29. }

·                     将用于回调方法的委托传递给 BeginInvoke。异步调用完成后,将在 ThreadPool 线程上执行该方法。该回调方法将调用 EndInvoke。注意:该回调函数的执行是在另外一个线程上。

  1. using System;
  2. using System.Threading;
  3. namespace Examples.AdvancedProgramming.AsynchronousOperations
  4. {
  5. public class AsyncMain
  6. {
  7. // Asynchronous method puts the thread id here.
  8. private static int threadId;
  9. static void Main() {
  10. // Create an instance of the test class.
  11. AsyncDemo ad = new AsyncDemo();
  12. // Create the delegate.
  13. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
  14. // Initiate the asychronous call.  Include an AsyncCallback
  15. // delegate representing the callback method, and the data
  16. // needed to call EndInvoke.
  17. IAsyncResult result = caller.BeginInvoke(3000,
  18. out threadId,
  19. new AsyncCallback(CallbackMethod),
  20. caller );
  21. Console.WriteLine("Press Enter to close application.");
  22. Console.ReadLine();
  23. }
  24. // Callback method must have the same signature as the
  25. // AsyncCallback delegate.
  26. static void CallbackMethod(IAsyncResult ar)
  27. {
  28. // Retrieve the delegate.
  29. AsyncMethodCaller caller = (AsyncMethodCaller) ar.AsyncState;
  30. // Call EndInvoke to retrieve the results.
  31. string returnValue = caller.EndInvoke(out threadId, ar);
  32. Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
  33. threadId, returnValue);
  34. }
  35. }
  36. }

二、使用 IAsyncResult 调用异步方法(使用层面)

.NET Framework 的许多方面都支持异步编程功能,这些方面包括:

·                     文件 IO、流 IO、套接字 IO。

·                     网络。

·                     远程处理信道(HTTP、TCP)和代理。

·                     使用 ASP.NET 创建的 XML Web services。

·                     ASP.NET Web 窗体。

·                     使用 MessageQueue 类的消息队列。

这些已经实现了异步操作的类或组件,可以直接调用其异步方法(以Begin和End开头)。调用异步方法后等待结果可以参考“异步调用同步方法”的处理。

三、基于 IAsyncResult 的异步设计模式(设计层面)

待续...

C#中的异步调用及异步设计模式(一)的更多相关文章

  1. C#“同步调用”、“异步调用”、“异步回调”

    本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: ); //模拟该方法运 ...

  2. C#(同步调用、异步调用、异步回调)

    Review: 原作者虽然使用了汉字的类名,看起来十分蹩脚,但是,还是把同步调用.异步调用.异步回调的使用讲解的很详细的.原理讲解的很清晰. ------ 本文将主要通过“同步调用”.“异步调用”.“ ...

  3. C# 同步调用、异步调用、异步回调

    本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: public dele ...

  4. c# 异步调用(异步模式,基于事件)

    c# 异步调用之异步模式Func<string, IImageRequest, string> downloadString = (address, req) => { var cl ...

  5. C#中的异步调用及异步设计模式(二)——基于 IAsyncResult 的异步设计模式

    三.基于 IAsyncResult 的异步设计模式(设计层面) IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperationName 的两个方法来 ...

  6. C#中的异步调用及异步设计模式(三)——基于事件的异步模式

    四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: ·                 ...

  7. 委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)

    下面为即将被调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(i ...

  8. C# 委托的三种调用示例(同步调用、异步调用、异步回调)

    首先,通过代码定义一个委托和下面三个示例将要调用的方法: 代码如下: public delegate int AddHandler(int a,int b); public class 加法类 { p ...

  9. 整理 C#(同步调用、异步调用、异步回调)

    //闲来无事,巩固同步异步方面的知识,以备后用,特整理如下: class Program { static void Main(string[] args) { //同步调用 会阻塞当前线程,一步一步 ...

随机推荐

  1. phpstorm 不能提示代码tp 3.2 $this->display等 解决办法

    phpstorm->file->Setting->Directorires 里把 ThinkPHP/Model 目录设置为 Excluded ,保存.

  2. Julia - 函数的参数传递

    不定参数 不定参数的函数也称变参函数 函数的参数可以被定义成任意个 可以在最后一个参数后紧跟省略号“...”来定义变参函数 julia> bar(x, y, z...) = (x, y, z) ...

  3. Eclipse免reload设置

    在使用eclipse开发web项目的时候,有的时候需要通过运行看结果,但是如果项目很大,你改一句代码,也许就要重启一次,或者eclipse自动帮你reload,这样严重的影响开发的效率,这里只要修改一 ...

  4. 关于Python安装官方whl包和tar.gz包的方法详解

    Windows环境: 安装whl包:pip install wheel -> pip install **.whl 安装tar.gz包:cd到解压后路径,python setup.py inst ...

  5. ubuntu 解决“无法获得锁 /var/lib/dpkg/lock -open”的方法

      在ubuntu系统终端下,用apt-get install 安装软件的时候,如果在未完成下载的情况下将终端中断,此时 apt-get进程可能没有结束.结果,如果再次运行apt-get instal ...

  6. html调用OCX

    <body> <p>hello</p> <p></p> <object id="iett" classid=&qu ...

  7. linux 下的mysql 连接报错

    报错: Fri Jul 28 16:28:52 CST 2017 WARN: Establishing SSL connection without server’s identity verific ...

  8. 关于springboot中文件上传,properties配置

    spring.http.multipart.enabled=true #默认支持文件上传. spring.http.multipart.file-size-threshold=0 #支持文件写入磁盘. ...

  9. linux磁 盘分区 挂载

    f命令查看磁盘的分区和已经使用量 利用du命令查询当前目录下的所有目录/文件所占的容量 dumpe2fs查看分区的具体使用情况 磁盘的分区–命令fdisk fdisk /dev/sda 进入这个设备m ...

  10. aop编程术语