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# 异步调用简单例子(转载)
首先来看一个简单的例子: 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务 这也是日 ...
随机推荐
- css引用方式
网页中引用CSS样式 内联样式 行内样式表 外部样式表 链接式 导入式 内嵌方式 style标签 <!doctype html> <html> <head> < ...
- css/css3实现未知宽高元素的垂直居中和水平居中
题目:.a{ width: 200px; height: 200px; background-color: #ccc;} <body> <div class="a" ...
- JasperReport报表导出踩坑实录
写在最前面 翻了翻博客,因为太忙,已经好久没认真总结过了. 正好趁着今天老婆出门团建的机会,记录下最近这段时间遇到的大坑-JasperReport. 六月份的时候写过一篇利用poi文件导入导出的小De ...
- 第六章 声明式服务调用: Spring Cloud Feign
我们在使用 Spring Cloud Ribbon 时, 通常都会利用它对 RestTemplate 的请求拦截来实现对依赖服务的接口调用, 而 RestTemplate 已经实现了对 HTTP 请求 ...
- jmeter4.0脚本录制
Jmeter录制脚本有两种方式.1.通过第三方工具录制比如:Badboy,然后转化为jmeter可用的脚本:2.使用jmeter本身自带的录制脚本功能. 本次使用jmeter本身自带的录制脚本功能 ...
- leetcode 数组array
120. Triangle 给出一个三角形(数据数组),找出从上往下的最小路径和.每一步只能移动到下一行中的相邻结点上. 解法,自底向上 The idea is simple. Go from bot ...
- 1.celery概述
1. 问题抛出 我们在做网站后端程序开发时,会碰到这样的需求:用户需要在我们的网站填写注册信息,我们发给用户一封注册激活邮件到用户邮箱,如果由于各种原因,这封邮件发送所需时间较长,那么客户端将会等待很 ...
- Gearmand 任务分发系统
简介: Gearmand 是一个用来把工作委派给其它机器.分布式的调用更适合做某项工作的机器.并发的做某项工作在多个调用间做负载均衡.或用来调用其它语言的函数的系统. 简单来讲,就是客户端程序把请求提 ...
- Python 调用阿里云 API 收集 ECS 数据
#!/usr/bin/env python # coding: utf-8 # author: Wang XiaoQiang ''' 功能介绍: 1.调用阿里云API,收集所有区域 ECS 信息 2. ...
- Java并发之AQS详解(转)
一.概述 谈到并发,不得不谈ReentrantLock:而谈到ReentrantLock,不得不谈AbstractQueuedSynchronized(AQS)! 类如其名,抽象的队列式的同步器,AQ ...