C#中的异步调用及异步设计模式(二)——基于 IAsyncResult 的异步设计模式
三、基于 IAsyncResult 的异步设计模式(设计层面)
IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperationName 的两个方法来实现原同步方法的异步调用,如 FileStream 类提供了 BeginRead 和 EndRead 方法来从文件异步读取字节,它们是 Read 方法的异步版本
Begin 方法包含同步方法签名中的任何参数,此外还包含另外两个参数:一个AsyncCallback 委托和一个用户定义的状态对象。委托用来调用回调方法,状态对象是用来向回调方法传递状态信息。该方法返回一个实现 IAsyncResult 接口的对象
End 方法用于结束异步操作并返回结果,因此包含同步方法签名中的 ref 和 out 参数,返回值类型也与同步方法相同。该方法还包括一个 IAsyncResult 参数,用于获取异步操作是否完成的信息,当然在使用时就必须传入对应的 Begin 方法返回的对象实例
开始异步操作后如果要阻止应用程序,可以直接调用 End 方法,这会阻止应用程序直到异步操作完成后再继续执行。也可以使用 IAsyncResult 的 AsyncWaitHandle 属性,调用其中的WaitOne等方法来阻塞线程。这两种方法的区别不大,只是前者必须一直等待而后者可以设置等待超时
如果不阻止应用程序,则可以通过轮循 IAsyncResult 的 IsCompleted 状态来判断操作是否完成,或使用 AsyncCallback 委托来结束异步操作。AsyncCallback 委托包含一个 IAsyncResult 的签名,回调方法内部再调用 End 方法来获取操作执行结果
- public class AsyncDemo
- {
- // Use in asynchronous methods
- private delegate string runDelegate();
- private string m_Name;
- private runDelegate m_Delegate;
- public AsyncDemo(string name)
- {
- m_Name = name;
- m_Delegate = new runDelegate(Run);
- }
- public string Run()
- {
- return "My name is " + m_Name;
- }
- public IAsyncResult BeginRun(AsyncCallback callBack, Object stateObject)
- {
- try
- {
- return m_Delegate.BeginInvoke(callBack, stateObject);
- }
- catch (Exception e)
- {
- // Hide inside method invoking stack
- throw e;
- }
- }
- public string EndRun(IAsyncResult ar)
- {
- if (ar == null)
- throw new NullReferenceException("Arggument ar can't be null");
- try
- {
- return m_Delegate.EndInvoke(ar);
- }
- catch (Exception e)
- {
- // Hide inside method invoking stack
- throw e;
- }
- }
- }
首先是 Begin 之后直接调用 End 方法,当然中间也可以做其他的操作
- class AsyncTest
- {
- static void Main(string[] args)
- {
- AsyncDemo demo = new AsyncDemo("jiangnii");
- // Execute begin method
- IAsyncResult ar = demo.BeginRun(null, null);
- // You can do other things here
- // Use end method to block thread until the operation is complete
- string demoName = demo.EndRun(ar);
- Console.WriteLine(demoName);
- }
- }
也可以用 IAsyncResult 的 AsyncWaitHandle 属性,我在这里设置为1秒超时
- class AsyncTest
- {
- static void Main(string[] args)
- {
- AsyncDemo demo = new AsyncDemo("jiangnii");
- // Execute begin method
- IAsyncResult ar = demo.BeginRun(null, null);
- // You can do other things here
- // Use AsyncWaitHandle.WaitOne method to block thread for 1 second at most
- ar.AsyncWaitHandle.WaitOne(1000, false);
- if (ar.IsCompleted)
- {
- // Still need use end method to get result, but this time it will return immediately
- string demoName = demo.EndRun(ar);
- Console.WriteLine(demoName);
- }
- else
- {
- Console.WriteLine("Sorry, can't get demoName, the time is over");
- }
- }
- }
不中断的轮循,每次循环输出一个 "."
- class AsyncTest
- {
- static void Main(string[] args)
- {
- AsyncDemo demo = new AsyncDemo("jiangnii");
- // Execute begin method
- IAsyncResult ar = demo.BeginRun(null, null);
- Console.Write("Waiting..");
- while (!ar.IsCompleted)
- {
- Console.Write(".");
- // You can do other things here
- }
- Console.WriteLine();
- // Still need use end method to get result, but this time it will return immediately
- string demoName = demo.EndRun(ar);
- Console.WriteLine(demoName);
- }
- }
最后是使用回调方法并加上状态对象,状态对象被作为 IAsyncResult 参数的 AsyncState
属性被传给回调方法。回调方法执行前不能让主线程退出,我这里只是简单的让其休眠了1秒。另一个与之前不同的地方是 AsyncDemo
对象被定义成了类的静态字段,以便回调方法使用
- class AsyncTest
- {
- static AsyncDemo demo = new AsyncDemo("jiangnii");
- static void Main(string[] args)
- {
- // State object
- bool state = false;
- // Execute begin method
- IAsyncResult ar = demo.BeginRun(new AsyncCallback(outPut), state);
- // You can do other thins here
- // Wait until callback finished
- System.Threading.Thread.Sleep(1000);
- }
- // Callback method
- static void outPut(IAsyncResult ar)
- {
- bool state = (bool)ar.AsyncState;
- string demoName = demo.EndRun(ar);
- if (state)
- {
- Console.WriteLine(demoName);
- }
- else
- {
- Console.WriteLine(demoName + ", isn't it?");
- }
- }
- }
对于一个已经实现了 BeginOperationName 和 EndOperationName
方法的对象,我们可以直接用上述方式调用,但对于只有同步方法的对象,我们要对其进行异步调用也不需要增加对应的异步方法,而只需定义一个委托并使用其
BeginInvoke 和 EndInvoke 方法就可以了
四、基于事件的异步模式(设计层面)
待续...
C#中的异步调用及异步设计模式(二)——基于 IAsyncResult 的异步设计模式的更多相关文章
- C#中的异步调用及异步设计模式(三)——基于事件的异步模式
四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: · ...
- C#中的异步调用及异步设计模式(一)
近期项目中使用了不少异步操作,关于“异步”做个总结.总结的内容大部分都来自于MSDN,还有一些自己的心得. 关于“异步”的使用可分为:使用层面和类库设计层面,细分如下: 一.使用异步方式调用同步方法( ...
- VB.NET中使用代表对方法异步调用
按照我们常规的思维方式,计算机应该是干完一件事,然后再干下一件.用术语来说,这种执行任务的方式叫做同步执行(Synchronous Execution).既然这样,那么为什么要引入异步执行的概念呢? ...
- MacOS和iOS开发中异步调用与多线程的区别
很多童鞋可能对Apple开发中的异步调用和多线程的区别不是太清楚,这里本猫将用一些简单的示例来展示一下它们到底直观上有神马不同. 首先异步调用可以在同一个线程中,也可以在多个不同的线程中.每个线程都有 ...
- .Net组件程序设计之异步调用
.Net组件程序设计之异步调用 说到异步调用,在脑海中首先想到就是BeginInvoke(),在一些常用对象中我们也会常常见到Invoke()和BeginInvoke(), 要想让自己的组件可以被客户 ...
- c#异步调用
首先来看一个简单的例子: 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务 这也是日 ...
- 序列化和反序列化,异步调用web/wcf/函数
//xml序列化 public static string Seria(DataSet ds) { XmlSerializer serializer = new XmlSerializer(typeo ...
- C#:Func的同步、异步调用(转)
实际开发中,对于一些耗时较长的操作,我们往往会将其封装成异步方式调用,以加速系统响应或改善用户体验,下面是一个示例: 有一个现成的类MyMath,里面有一个Add方法: 1 public class ...
- c# 异步调用简单例子(转载)
首先来看一个简单的例子: 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务 这也是日 ...
随机推荐
- HDU1869 六度分离
/* 六度分离 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- SharePoint 事件 2137 / 2138 :SharePoint 运行状况分析器检测到错误。驱动器的可用空间不足。
转自MSDN:http://technet.microsoft.com/zh-cn/library/ff805057.aspx 摘要:服务器场中的一个或多个服务器上的磁盘驱动器的可用空间不足. 注意: ...
- 一,我的Android Studio 3.0.1 安装过程
安装成功于20171231的0:46分. 简要记录我的安装过程如下: 一,安装JDK1.8.X 二,安装ANDROID STUDIO.ZIP 三,运行AS,后按提示下载SDK,NDK,必要时设置一下J ...
- curl_setopt设置发送cookie信息
1.php curl访问会话传递问题 curl_setopt($ch , CURLOPT_COOKIE , 'PHPSESSID=A7281E0926CB37D791AD464CDD646CF2') ...
- HTTP头的Expires与Cache-control区别
2010年3月24日 a18ccms 发表评论 阅读评论 今天在群里聊天.说道了Expires.这里来说明下这两个的区别吧. 1.概念 Cache-control 用于控制HTTP缓存(在HTTP/1 ...
- PHP对全局变量_GET、_POST中特殊字符的过滤
$sVariablesOrder = ini_get( 'variables_order' ); $request = array(); //过滤不安全数据 for ( $i ...
- day9-IO心得
Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SSH Tws ...
- springboot-shiro chapter03 login
简介:这一节主要是集成shiro进行鉴权, 用户登录/退出 环境: IDEA15+JDK1.8+Maven3+ 代码: https://git.oschina.net/xinshu/springboo ...
- 3、数据类型一:strings
题外: 学习过程参考三份资料:<Redis入门指南>.<Redis实战>.http://redis.io 后面的学习笔记中会引入它们的内容或代码,在这里统一说明,后面笔记中便不 ...
- FTP服务器(SOCKET)返回异常 500 Command not understood
出现着这样的问题,一般是NLST中的参数包含特殊字符,如"\n",所以在发送SOCKET命令时,一定要检查命令参数的合法性.