当前位置: 首页 > 编程日记 > 正文

异步编程模型--使用 IAsyncResult 对象

先推荐阅读下面的资料:

MSDN:异步编程设计模式

IBM developerworks: 使用异步 I/O 大大提高应用程序的性能

参考博文:

1、正确使用异步操作

2、Lab:体会ASP.NET异步处理请求的效果

3、WCF中的异步调用

4、WCF从理论到实践(11)-异步

5、异步编程

.NET Framework 为异步操作提供两种设计模式:
1、使用 IAsyncResult 对象的异步操作。
2、使用事件的异步操作。

IAsyncResult接口类型

    [ComVisible(true)]
    
public interface IAsyncResult
    {
        
// 摘要:
        
//     获取用户定义的对象,它限定或包含关于异步操作的信息。
        
//
        
// 返回结果:
        
//     用户定义的对象,它限定或包含关于异步操作的信息。
        object AsyncState { get; }
        
//
        
// 摘要:
        
//     获取用于等待异步操作完成的 System.Threading.WaitHandle。
        
//
        
// 返回结果:
        
//     用于等待异步操作完成的 System.Threading.WaitHandle。
        WaitHandle AsyncWaitHandle { get; }
        
//
        
// 摘要:
        
//     获取异步操作是否同步完成的指示。
        
//
        
// 返回结果:
        
//     如果异步操作同步完成,则为 true;否则为 false。
        bool CompletedSynchronously { get; }
        
//
        
// 摘要:
        
//     获取异步操作是否已完成的指示。
        
//
        
// 返回结果:
        
//     如果操作完成则为 true,否则为 false。
        bool IsCompleted { get; }
    }


下面是使用 IAsyncResult 对象的测试代码。

 public delegate string AsyncDelegate(int callDuration, out int threadId);
    
class Program
    {
        
static void Main(string[] args)
        {
            Fun1();
            Console.ReadLine();
        }

        
private static int threadId;

        
//阻塞等待   使用 EndInvoke 等待异步调用  
        static void Fun1()
        {
            
//创建示例类的实例。
            AsyncDemo ad = new AsyncDemo();
            
// 创建委托
            AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
            
// 委托在这里开始异步调用。
            IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, nullnull);
            
//人为的线程阻塞。
            Thread.Sleep(0);
            Console.WriteLine(
"主线程 {0}开始工作",Thread.CurrentThread.ManagedThreadId);
            
// 委托开始EndInvoke调用,这个过程会使主线程等待异步调用完成并返回结果。
            string ret = dlgt.EndInvoke(out threadId, ar);
            Console.WriteLine(
"异步线程 {0},返回值 \"{1}\".", threadId, ret);
            Console.WriteLine(
"主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
        }
        
        
//阻塞等待  使用 WaitHandle 等待异步调用
        static void Fun2()
        {
            AsyncDemo ad 
= new AsyncDemo();
            AsyncDelegate dlgt 
= new AsyncDelegate(ad.TestMethod);
            IAsyncResult ar 
= dlgt.BeginInvoke(5000,out threadId, nullnull);
            Thread.Sleep(
0);
            Console.WriteLine(
"主线程 {0}开始工作", Thread.CurrentThread.ManagedThreadId);
            
//主线程在这里等待,直到异步线程执行完。
            ar.AsyncWaitHandle.WaitOne();
            
// 和前一方案的区别在于,你可以在异步调用完成后,获取异步调用返回值之前
            
//在这里做点任何你想作的事。
            
//调用EndInvoke获取异步调用的返回结果.
            string ret = dlgt.EndInvoke(out threadId, ar);
            Console.WriteLine(
"异步线程 {0},返回值 \"{1}\".", threadId, ret);
            Console.WriteLine(
"主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
        }

        
//轮询状态    轮询异步调用完成
        static void Fun3()
        {
            AsyncDemo ad 
= new AsyncDemo();
            AsyncDelegate dlgt 
= new AsyncDelegate(ad.TestMethod);
            IAsyncResult ar 
= dlgt.BeginInvoke(5000,out threadId, nullnull);
            Console.WriteLine(
"主线程 {0}开始工作", Thread.CurrentThread.ManagedThreadId);
            
//这里每隔10毫秒就检测(轮询)一下异步执行的状态,
            
//直到异步调用完成,IsCompleted的值变为ture为止。
            while (ar.IsCompleted == false)
            {
                Thread.Sleep(
10);
            }

            
//还记得微软的那个善意的提醒吗?虽然IsCompleted为true了,
            
//我们还是调用一下EndInvoke,来获取返回值。
            string ret = dlgt.EndInvoke(out threadId, ar);
            Console.WriteLine(
"异步线程 {0},返回值 \"{1}\".", threadId, ret);
            Console.WriteLine(
"主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
        }

        
//通知机制    异步调用完成时执行回调方法
        static void Fun4()
        {
            AsyncDemo ad 
= new AsyncDemo();
            AsyncDelegate dlgt 
= new AsyncDelegate(ad.TestMethod);
            
//注意第三个参数,这就是我们要用到的回调方法。
            
//第四个参数更为有趣,它可以是任何Object对象,这里它就是
            
//执行异步调用的委托本身,把委托本身传递进去的原因在下面可以看到。
            Console.WriteLine("主线程 {0}开始工作", Thread.CurrentThread.ManagedThreadId);
            IAsyncResult ar 
= dlgt.BeginInvoke(5000,out threadId, new AsyncCallback(CallbackMethod), dlgt);
            Console.WriteLine(
"主线程 {0}结束工作", Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
        
//回调函数必须严格的遵照AsyncCallback委托的签名。
        static void CallbackMethod(IAsyncResult ar)
        {
            
//在这里,上面那个dlgt作为参数的作用得到了体现,原来它就是为了完成对EndInvoke的调用啊。
            AsyncDelegate dlgt = (AsyncDelegate)ar.AsyncState;
            
//通过对EndInvoke的调用获取返回值。
            string ret = dlgt.EndInvoke(out threadId, ar);
            Console.WriteLine(
"异步线程 {0},返回值 \"{1}\".", threadId, ret);
        }
    }
    
//使用异步编程模型 
    public class AsyncDemo
    {
        
public string TestMethod(int callDuration, out int threadId)
        {
            Console.WriteLine(
"异步方法开始工作");
            Thread.Sleep(callDuration);
            threadId 
= Thread.CurrentThread.ManagedThreadId; 
            
return "异步方法执行时间 " + callDuration.ToString();
        }
    }

执行结果:

Fun1--------------------

异步方法开始工作
主线程 10开始工作
异步线程 7,返回值 "异步方法执行时间 5000".
主线程10结束工作
Fun2---------------------
异步方法开始工作
主线程 10开始工作
异步线程 7,返回值 "异步方法执行时间 5000".
主线程10结束工作
Fun3---------------------

主线程 10开始工作
异步方法开始工作
异步线程 7,返回值 "异步方法执行时间 5000".
主线程10结束工作
Fun4---------------------
主线程 10开始工作
主线程 10结束工作
异步方法开始工作
异步线程 7,返回值 "异步方法执行时间 5000".
--------------------------

工作当中有一个调用ActiveMQ的产品,每天大概是上万的消息。压力也不是很大。最近总是出现调用MQ阻塞的情况。负责MQ的同事也没有找到原因。

我是想寻找一个消息队列的代替品。 上面的第四个方法,异步线程不阻塞调用线程,当然调用线程也无需处理调用结果,貌似可以作为一个代替方案。


转载于:https://www.cnblogs.com/tenghoo/archive/2010/01/07/ARM_IAsyncResult.html

相关文章:

对XX证券报关于物联网操作系统的几个问题的答复

XX证券报提问了几个关于物联网和物联网操作系统的问题,个人表达了一些粗陋的观点,在这里发表出来,与行业朋友交流和探讨。物联网行业最需要解决的问题是什么?虽然物联网这个行业被炒得比较热,但是截至目前,…

Java基础 - 面向对象 - 构造方法

在类中除了成员方法之外,还存在一种特殊类型的方法,那就是构造方法。构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。 构造方法的特点: 构造方法没…

1105 Spiral Matrix 给定数组向螺旋矩阵中填入数据

两个测试用例超时,可直接跳转到 目录 超时点1 超时点2 ​​​​​​​ 要做的事情是,将数组按照非升序/降序,顺时针从外围到内部一圈一圈地把数据填到矩阵中,并打印出来。也就是将数组排好序后,将矩阵的坐标和数组…

一晚上就能让你小腹变小的方法 - 健康程序员,至尚生活!

仅一晚上针对小腹的锻炼就会让它明显收紧,很不可思议吧?但它确实发生了。形体教练向我们推荐:做30次转身运动(双手抱在脑后站立,迅速分别向左右两侧依次扭转上肢,注意不要以膝盖为轴,使运动轴心保持在骨盆以…

Alpha 冲刺 (2/10)

前言 队名:拖鞋旅游队组长博客:https://www.cnblogs.com/Sulumer/p/9960487.html作业博客:https://edu.cnblogs.com/campus/fzu/Grade2016SE/homework/2365组内情况 燃尽图任务分布github签入记录苏路明(组长)过去两天…

互联网对erp行业到底有什么影响

1 财务管理的影响 总账、 应收应付、资金计划,支付管理。 生产计划的影响。 重大的疑惑。 转载于:https://www.cnblogs.com/sdgxbooy/p/8892655.html

PAT甲级排队问题合集 (持续更新中)

已加入的习题 A1014,A1017 问题1和2共性 1. 都是排队问题 2. 都有一条黄线 3. 都需要找到最先离开人的队伍 4. 都有着服务时间段限制(迟于某个时间点来不予受理) 问题1:1014 Waiting in Line 问题链接:1014 Waiting in Line 这一题,…

第三章:创建用户界面组件--可视化组件(一)

1.可视化组件 1.1关于可视化组件 可视化组件的特征包括:size(大小)、事件、样式、皮肤、行为。 行为:当组件被触发时,视觉,音乐效果的变化。 1.1 .1Spark and Halo 组件 Spark是flex 4中新加的组件。halo仍旧继承了以…

Rust 1.30带来更多元编程支持,并改进了模块系统

Rust的最新版本1.30扩展了过程宏,允许它们定义新的属性和类似于函数的宏。此外,它简化了Rust模块系统,使其更加一致、直观。 Rust 1.30引入了两种新类型的过程宏,“类属性的过程宏”和“类函数的过程宏”。过程宏是Rust元编程的基…

两种最大堆建堆方式

都是用完全二叉树的静态存储方式,下标从1开始。 No.1 先按照数组的次序填入完全二叉树,再从倒数第一个非叶子节点开始,一个个地看是不是要向下调整,一直下调到不能再调。 void downAdjust(int low,int high){int i low;int j …

汉字验证码和算式验证码

大家知道简单数字或者字母验证码很容易被破解,但是算式验证码或者中文汉字验证码不容易被破解, 所以建议大家在使用验证码的时候,尽量用算式验证码或者中文汉字验证码。 下面是我写的两种验证码代码,有用到的朋友可以参考下&#…

自定义Linq的Distinct

代码 1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.ComponentModel;4 usingSystem.Data;5 usingSystem.Drawing;6 usingSystem.Linq;7 usingSystem.Text;8 usingSystem.Windows.Forms;9 10 namespaceLinqTest11 {12 publicpartialclassForm1 : Form13 {14 p…

Python itertools 实现全组合

>>> import itertools >>> data itertools.product([A, B], [1, 2, 3]) >>> list(data) [(A, 1), (A, 2), (A, 3), (B, 1), (B, 2), (B, 3)] 转载于:https://www.cnblogs.com/xiecl/p/9961825.html

PAT(甲级)2021年春季考试 7-3 Structure of Max-Heap

考察:建堆,字符串的处理 建堆上,跳了坑,才发现自己之前的方法过于笨拙,详情见两种最大堆建堆方式 字符串处理上,走的弯路更大,但是也因此牢记了两个技巧 1. cin>>str可以用getline(cin…

[linux内核][linux中断]——软中断机制

点击打开链接 一,linux软中断的概念软中断(softirq)常常表示可延迟函数的所有种类,目前linux上使用的软中断个数是有限的,linux最多注册32个,目前使用了10个,在interrupt.h中定义,中…

JS中8个常见的陷阱

译者按: 漫漫编程路,总有一些坑让你泪流满面。 原文: Who said javascript was easy ? 译者: Fundebug为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。 这里我们针对JavaScript初学者给出一些…

支持支付宝(Alipay)付款的三个美国主机商

这段时间买国外主机的筒子们越来越多,而付款就是首先摆在大家眼前的一道障碍,大部分美国主机商只能通过信用卡购买,付款不方便。因为这个原因,很多人的美国主机都是从国内的公司或者个人买的,无法享受美国主机的优质服…

(C++)string 的两种输入方式和输出方式

注&#xff1a;头文件如下 #include<string> #include<cstdio> #include<iostream>using namespace std; 注&#xff1a;第一种输入方式遇到回车停止读入&#xff0c;第二种输入方式遇到空格停止读入。 两种读入方式也都可以用来读字符数组。 int main()…

ob_get_contents();basename;file_get_contents用法

ob_get_contents(); ob_end_clean(); ob_start()使用ob_start()把输出那同输出到缓冲区&#xff0c;而不是到浏览器。然后用ob_get_contents得到缓冲区的数据。 ob_start()在服务器打开一个缓冲区来保存所有的输出。所以在任何时候使用echo &#xff0c;输出都将被加入缓冲区中…

零基础学汇编 --小甲鱼

来自http://www.51xue8.com/diannao/wangluobiancheng/2013-11-06/6584.html#fillback0100307b617b7b7b303232303266313839397b677b7b240000&anchortestanchor转载于:https://www.cnblogs.com/I-L-o-v-e-z-h-o-u/p/4235340.html

数据标准化_1

from sklearn.datasets import load_irisirisload_iris()#Z-score 数据标准化from sklearn.preprocessing import StandardScalerdata_standardStandardScaler().fit_transform(iris.data)# print(data_standard,data_standard)#Min-Maxfrom sklearn.preprocessing import MinM…

PAT(甲级)2021年春季考试 7-1 Arithmetic Progression of Primes

思路&#xff1a;用筛除法打素数表(与之相对的是枚举加逐个判断)是降低时间复杂度的第一个点&#xff0c;第二个点是运用上数学技巧&#xff0c;给定了等差数列的范围(2-MAX)&#xff0c;给定了个数&#xff0c;那么最大的等差是可以求出的。循环的第一层从最大等差开始&#x…

hadoop中HBase子项目入门讲解

HBase 是Hadoop的一个子项目,HBase采用了Google BigTable的稀疏的,面向列的数据库实现方式的理论,建立在hadoop的hdfs上,一方面里用了hdfs的高可靠性和可伸缩行,另外一方面里用 了BigTable的高效数据组织形式.可以说HBase为海量数据的real-time相应提供了很好的一个开源解决方案…

C++/C union使用记一下锅

//首先&#xff0c;学习编程一定要记得加几个群或者加几个讨论组&#xff0c;因为这样你才能不断地进步还有吵架/滑稽 记一下 关于使用union结构体时遇到的一些坑 To zero-initialize an object of type T means: — if T is a scalar type (3.9), the object is set to the va…

推荐60+ Flex开发参考网站

推荐60 Flex开发参考网站 下面是一些好的Flex开发的网站或者Flex资源&#xff0c;如果你使用Flex开发&#xff0c;可以参考一下。 网上找的&#xff0c;可以参考参考&#xff01;呵呵 新手入门参考: Adobe Flex 3 - adobe.comAdobe Flex Sample Applications - adobe.comVideo …

PAT(甲级)2020年秋季考试 7-4 Professional Ability Test

解题思路&#xff1a; 1.用拓扑排序判断给定的图是否是有向无环图(DAG) 在这个过程当中&#xff0c;对于入度为0的结点&#xff0c;在布尔数组中标记是初始结点 通过入队的结点个数是否等于总个数判断是不是DAG 注意&#xff1a;虽然有队列&#xff0c;但是不需要inq[]数组…

TestNG:org.openqa.selenium.os.UnixProcess$SeleniumWatchDog错误

在TestNG运行自动化测试用例的时候&#xff0c;浏览器FireFox正确打开&#xff0c;可是在测试用例运行完成后&#xff0c;我调用的是webdriver.quit()关闭程序的&#xff0c;结果却报以下错误&#xff1a; Sep 25, 2014 4:19:32 PM org.openqa.selenium.os.UnixProcess$Seleniu…

项目经理修炼手册 2.1.2 项目经理的基本功

具备以上素质的人&#xff0c;大体上可以算是具有基本的程序员素质了&#xff0c;但是想从程序员成为项目经理&#xff0c;必然还需要有一点进步&#xff0c;那额外的这些素质都有哪些呢&#xff1f; 曾经有人力资源的朋友问我要人&#xff0c;我介绍了几个技术上很不错的人&am…

CSS3动画过渡的jquery动态弹出框插件

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/w178191520/article/details/84111711 在线演示 本地下载

PAT(甲级)2021年春季考试 7-4 Recycling of Shared Bicycles

解题思路&#xff1a; 先用Floyd算法求出全员最短路径矩阵。 然后使用DFS进行遍历&#xff0c;遍历的原则是就近贪心&#xff0c;对于每一个点先遍历离他最近的未访问点。 记录访问点的个数&#xff0c;同时用数组存放已访问点&#xff0c;如果访问点的个数不等于输入点数1(…