C#中的异步调用及异步设计模式(一)
近期项目中使用了不少异步操作,关于“异步”做个总结。总结的内容大部分都来自于MSDN,还有一些自己的心得。
关于“异步”的使用可分为:使用层面和类库设计层面,细分如下:
一、使用异步方式调用同步方法(使用层面)。
二、使用 IAsyncResult 调用异步方法(使用层面)。
三、基于 IAsyncResult 的异步设计模式(设计层面)。
四、基于事件的异步模式(设计层面)。
关于上述异步编程的几个方面,下面分别做以详述。
一、使用异步方式调用同步方法(使用层面)
.NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义 BeginInvoke 和 EndInvoke 方法。BeginInvoke 方法可启动异步调用,EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。
该调用方式是使用委托进行异步调用,其实质是:调用“BeginInvoke”方法,公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行,该目标方法是在线程池线程运行的。
在异步调用启动后,在等待异步调用结果的时候,可以进行以下四种方法。
· 进行某些操作,然后调用 EndInvoke 一直阻止到调用完成。
- using System;
- using System.Threading;
- namespace Examples.AdvancedProgramming.AsynchronousOperations
- {
- public class AsyncMain
- {
- public static void Main()
- {
- // The asynchronous method puts the thread id here.
- int threadId;
- // Create an instance of the test class.
- AsyncDemo ad = new AsyncDemo();
- // Create the delegate.
- AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
- // Initiate the asychronous call.
- IAsyncResult result = caller.BeginInvoke(3000,
- out threadId, null, null);
- Thread.Sleep(0);
- Console.WriteLine("Main thread {0} does some work.",
- Thread.CurrentThread.ManagedThreadId);
- // 调用此方法将会一直等待异步操作完成,并阻塞当前线程。
- string returnValue = caller.EndInvoke(out threadId, result);
- Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
- threadId, returnValue);
- }
- }
- }
· 进行某些操作,然后使用
IAsyncResult..::.AsyncWaitHandle 属性获取 WaitHandle,使用它的 WaitOne
方法(该方法可以设置一个超时时间)一直阻止执行直到发出 WaitHandle 信号,然后调用 EndInvoke。
- using System;
- using System.Threading;
- namespace Examples.AdvancedProgramming.AsynchronousOperations
- {
- public class AsyncMain
- {
- static void Main()
- {
- // The asynchronous method puts the thread id here.
- int threadId;
- // Create an instance of the test class.
- AsyncDemo ad = new AsyncDemo();
- // Create the delegate.
- AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
- // Initiate the asychronous call.
- IAsyncResult result = caller.BeginInvoke(3000,
- out threadId, null, null);
- Thread.Sleep(0);
- Console.WriteLine("Main thread {0} does some work.",
- Thread.CurrentThread.ManagedThreadId);
- // 调用此方法将会一直等待异步操作完成,并阻塞当前线程。
- result.AsyncWaitHandle.WaitOne();
- // Perform additional processing here.
- // Call EndInvoke to retrieve the results.
- string returnValue = caller.EndInvoke(out threadId, result);
- Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
- threadId, returnValue);
- }
- }
- }
· 进行某些操作,然后轮询由 BeginInvoke 返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。
- using System;
- using System.Threading;
- namespace Examples.AdvancedProgramming.AsynchronousOperations
- {
- public class AsyncMain
- {
- static void Main()
- {
- // The asynchronous method puts the thread id here.
- int threadId;
- // Create an instance of the test class.
- AsyncDemo ad = new AsyncDemo();
- // Create the delegate.
- AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
- // Initiate the asychronous call.
- IAsyncResult result = caller.BeginInvoke(3000,
- out threadId, null, null);
- // 等待结果返回
- while (result.IsCompleted == false)
- {
- Thread.Sleep(10);
- }
- // Call EndInvoke to retrieve the results.
- string returnValue = caller.EndInvoke(out threadId, result);
- Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
- threadId, returnValue);
- }
- }
- }
· 将用于回调方法的委托传递给 BeginInvoke。异步调用完成后,将在 ThreadPool 线程上执行该方法。该回调方法将调用 EndInvoke。注意:该回调函数的执行是在另外一个线程上。
- using System;
- using System.Threading;
- namespace Examples.AdvancedProgramming.AsynchronousOperations
- {
- public class AsyncMain
- {
- // Asynchronous method puts the thread id here.
- private static int threadId;
- static void Main() {
- // Create an instance of the test class.
- AsyncDemo ad = new AsyncDemo();
- // Create the delegate.
- AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
- // Initiate the asychronous call. Include an AsyncCallback
- // delegate representing the callback method, and the data
- // needed to call EndInvoke.
- IAsyncResult result = caller.BeginInvoke(3000,
- out threadId,
- new AsyncCallback(CallbackMethod),
- caller );
- Console.WriteLine("Press Enter to close application.");
- Console.ReadLine();
- }
- // Callback method must have the same signature as the
- // AsyncCallback delegate.
- static void CallbackMethod(IAsyncResult ar)
- {
- // Retrieve the delegate.
- AsyncMethodCaller caller = (AsyncMethodCaller) ar.AsyncState;
- // Call EndInvoke to retrieve the results.
- string returnValue = caller.EndInvoke(out threadId, ar);
- Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
- threadId, returnValue);
- }
- }
- }
二、使用 IAsyncResult 调用异步方法(使用层面)
.NET Framework 的许多方面都支持异步编程功能,这些方面包括:
· 文件 IO、流 IO、套接字 IO。
· 网络。
· 远程处理信道(HTTP、TCP)和代理。
· 使用 ASP.NET 创建的 XML Web services。
· ASP.NET Web 窗体。
· 使用 MessageQueue 类的消息队列。
这些已经实现了异步操作的类或组件,可以直接调用其异步方法(以Begin和End开头)。调用异步方法后等待结果可以参考“异步调用同步方法”的处理。
三、基于 IAsyncResult 的异步设计模式(设计层面)
待续...
C#中的异步调用及异步设计模式(一)的更多相关文章
- C#“同步调用”、“异步调用”、“异步回调”
本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: ); //模拟该方法运 ...
- C#(同步调用、异步调用、异步回调)
Review: 原作者虽然使用了汉字的类名,看起来十分蹩脚,但是,还是把同步调用.异步调用.异步回调的使用讲解的很详细的.原理讲解的很清晰. ------ 本文将主要通过“同步调用”.“异步调用”.“ ...
- C# 同步调用、异步调用、异步回调
本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: public dele ...
- c# 异步调用(异步模式,基于事件)
c# 异步调用之异步模式Func<string, IImageRequest, string> downloadString = (address, req) => { var cl ...
- C#中的异步调用及异步设计模式(二)——基于 IAsyncResult 的异步设计模式
三.基于 IAsyncResult 的异步设计模式(设计层面) IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperationName 的两个方法来 ...
- C#中的异步调用及异步设计模式(三)——基于事件的异步模式
四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: · ...
- 委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)
下面为即将被调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(i ...
- C# 委托的三种调用示例(同步调用、异步调用、异步回调)
首先,通过代码定义一个委托和下面三个示例将要调用的方法: 代码如下: public delegate int AddHandler(int a,int b); public class 加法类 { p ...
- 整理 C#(同步调用、异步调用、异步回调)
//闲来无事,巩固同步异步方面的知识,以备后用,特整理如下: class Program { static void Main(string[] args) { //同步调用 会阻塞当前线程,一步一步 ...
随机推荐
- linux查看进程是否存在,不存在则重启
ps -ef | grep 程序名| grep -v grep | wc -l cd $(dirname $) source ~/.bash_profile count=`ps -ef | grep ...
- 用 Sqlmap 识别 WAF
命令: ┌─[root@sch01ar]─[~] └──╼ #sqlmap -u "http://www.sch01ar.com/" --identify-waf --batch ...
- Python操作中缓存Redis
Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...
- winform 实现局部更新(如ajax实现)而整个界面不产生闪烁的解决方案
转自原文winform 实现局部更新(如ajax实现)而整个界面不产生闪烁的解决方案 一.通过对窗体和控件使用双缓冲来减少图形闪烁(当绘制图片时出现闪烁时,使用双缓冲) 对于大多数应用程序,.NET ...
- leetcode36
public class Solution { public bool IsValidSudoku(char[,] board) { ; i < ; i++) { var dic = new D ...
- leetcode707
数据结构的题,从网上找到的实现方式,先记录下来. class MyLinkedList { public: /** Initialize your data structure here. */ My ...
- delphi IOS 简单类型转换
aUrl: NSString; cmdurl: NSURL; AbsoluteFileName: string; cmdurl := NSURL.URLWithString(aUrl); cmdurl ...
- centos安装rvm报错@curl -L get.rvm.io | bash -s stable fails on cent OS
It is a security feature introduced in the latest version of RVMhttps://github.com/wayneeseguin/rvm/ ...
- nginx root与alias区别
引用于文章https://blog.csdn.net/line_aijava/article/details/71473793 root: Sets the root directory for re ...
- Tmux (转)
Tmux是一个优秀的终端复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权.使用它最直观的好处就是,通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再“ ...