当我们用到C#类许多耗时的函数XXX时,总会存在同名的类似BeginXXX,EndXXX这样的函数。

例如Stream抽象类的Read函数就有

        public abstract int Read(byte[] buffer, int offset, int count);

        public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state);

        public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state);

这也就是所谓的APM异步编程模型,基于委托实现,其实就是启动了一个后台线程(主线程结束,则该线程结束),其中IAsyncResult就是异步状态接口,用来检测异步是否完成。

代码模拟场景1:

每到大热天的中午就不想动,出门就是一身汗,所以一般午餐时间我都选择定外卖,正好等外卖这段时间还可以完善一下上午的工作内容。这就相当于委托一名外卖小哥异步帮我送一份快餐过来,这段时间我继续干我的事情。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace BeginInvoke
{
class Program
{
//声明一个送外卖的委托类型
private delegate int DeliveryDelegate(string foodname);
static void Main(string[] args)
{
Console.WriteLine("天气太热,带电话叫外卖小哥送一份番茄炒蛋"); //声明一个外卖小哥,委托他去帮我拿午餐。
DeliveryDelegate DeliveryBoy = new DeliveryDelegate(GetFood); //开始CALL电话(异步调用,由于还没用到回调函数,后两个参数填空)
IAsyncResult ar = DeliveryBoy.BeginInvoke("番茄炒蛋", null, null); //继续干自己的事……
Console.WriteLine("完善上午的工作~大概5分钟完成");
Thread.Sleep();
Console.WriteLine("完善20%");
Thread.Sleep();
Console.WriteLine("完善40%");
Thread.Sleep();
Console.WriteLine("完善60%");
Thread.Sleep();
Console.WriteLine("完善80%");
Thread.Sleep();
Console.WriteLine("完善100%");
Console.WriteLine("完善工作完成");//但是外卖还没到
Console.WriteLine("等外卖……好饿,估计还要5分钟才到"); //此时调用EndInvoke会阻塞住线程直到异步调用完成,这时相当于我就主动蹲在门口等外卖小哥送上门,如果小哥先到,只能在门口等我办完事~。
int money = DeliveryBoy.EndInvoke(ar);
Console.WriteLine("给快递小哥" + money + "元,开吃");
} /// <summary>
/// 获取食物
/// </summary>
/// <param name="foodname">食物名</param>
/// <returns>价格</returns>
private static int GetFood(string foodname)
{
Console.WriteLine("外卖小哥顶着烈日送餐ing,预计10分钟后到");
Thread.Sleep();
Console.WriteLine("外卖到达~" + foodname);
//不管什么菜一律10元钱!
return ;
}
}
}

运行结果:

天气太热,带电话叫外卖小哥送一份番茄炒蛋
完善上午的工作~大概5分钟完成
外卖小哥顶着烈日送餐ing,预计10分钟后到
完善20%
完善40%
完善60%
完善80%
完善100%
完善工作完成
等外卖……好饿,估计还要5分钟才到
外卖到达~番茄炒蛋
给快递小哥10元,开吃

注:如果使用ar.AsyncWaitHandle.WaitOne();可以设置指定等待时间间隔

            if (ar.AsyncWaitHandle.WaitOne())//也会阻塞住线程直到异步调用完成,EndInvoke之后会自动收到Set信号。
{
int money = DeliveryBoy.EndInvoke(ar);
Console.WriteLine("给快递小哥" + money + "元,开吃");
//如果调用ar.AsyncWaitHandle.WaitOne();,记得EndInvoke后要主动Close哟!
ar.AsyncWaitHandle.Close();
}

代码模拟场景2:

之前的场景,如果我没有做完工作,那么外卖小哥只能在门口一直等我做完事情(没办法通知我外卖到了,只有我主动去检查),这个时候回调函数就派上用处了,我就再也不用担心外卖什么时候到,因为我又委托一个人专门帮我在门口盯着外卖小哥!

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace BeginInvoke
{
class Program
{
//声明一个送外卖的委托类型
private delegate int DeliveryDelegate(string foodname);
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now.ToString());
Console.WriteLine("天气太热,带电话叫外卖小哥送一份番茄炒蛋"); //声明一个外卖小哥,委托他去帮我拿午餐。
DeliveryDelegate DeliveryBoy = new DeliveryDelegate(GetFood); //开始CALL电话(异步调用,AsyncCallback其实也是一个delegate类型,实例化delegate委托一个人专门帮我在门口盯着外卖小哥)
IAsyncResult ar = DeliveryBoy.BeginInvoke("番茄炒蛋", new AsyncCallback(GetFoodCallback), "番茄炒蛋"); //继续干自己的事……
Console.WriteLine("完善上午的工作~大概5分钟完成");
Thread.Sleep();
Console.WriteLine("完善20%");
Thread.Sleep();
Console.WriteLine("完善40%");
Thread.Sleep();
Console.WriteLine("完善60%");
Thread.Sleep();
Console.WriteLine("完善80%");
Thread.Sleep();
Console.WriteLine("完善100%");
Console.WriteLine("完善工作完成");//但是外卖还没到 Console.WriteLine("外卖估计还要5分钟才到,时间不等人,撸一盘"); //中途外卖到了,回调函数帮我付钱拿外卖,我继续撸。
Console.WriteLine("LOL……一局10分钟");
for (int i = ; i < ; i++)
{
Thread.Sleep();
Console.WriteLine("过去了1分钟");
} Console.WriteLine("LOL拿到了首胜!,吃饭"); if (ar.IsCompleted)
{
Console.WriteLine("好吃~");
}
} /// <summary>
/// 获取食物
/// </summary>
/// <param name="foodname">食物名</param>
/// <returns>价格</returns>
private static int GetFood(string foodname)
{
Console.WriteLine("外卖小哥顶着烈日送餐ing,预计10分钟后到");
Thread.Sleep();
Console.WriteLine("外卖到达~" + foodname);
//不管什么菜一律10元钱!
return ;
} /// <summary>
/// 异步完成,回调(完成时执行)
/// 回调在 ThreadPool 线程上执行。 ThreadPool 线程是后台线程,这些线程不会在主线程结束后保持应用程序的运行,因此示例的主线程必须休眠足够长的时间以便回调完成。
/// </summary>
/// <param name="ar">异步状态</param>
private static void GetFoodCallback(IAsyncResult ar)
{
AsyncResult result = (AsyncResult)ar;
DeliveryDelegate dd = result.AsyncDelegate as DeliveryDelegate;
int money = dd.EndInvoke(ar);
string foodname = ar.AsyncState as string;
Console.WriteLine("拿外卖!" + foodname + ",一共" + money + "元");
Console.WriteLine("付钱");
}
}
}

运行结果:

天气太热,带电话叫外卖小哥送一份番茄炒蛋
完善上午的工作~大概5分钟完成
外卖小哥顶着烈日送餐ing,预计10分钟后到
完善20%
完善40%
完善60%
完善80%
完善100%
完善工作完成
外卖估计还要5分钟才到,时间不等人,撸一盘
LOL……一局10分钟
过去了1分钟
过去了1分钟
过去了1分钟
过去了1分钟
过去了1分钟
外卖到达~番茄炒蛋
拿外卖!番茄炒蛋,一共10元
付钱
过去了1分钟
过去了1分钟
过去了1分钟
过去了1分钟
过去了1分钟
LOL拿到了首胜!,吃饭
好吃~

参考:

https://msdn.microsoft.com/zh-cn/library/ms228963(v=vs.110).aspx

https://msdn.microsoft.com/zh-cn/library/system.iasyncresult(v=vs.110).aspx

https://msdn.microsoft.com/zh-cn/library/2e08f6yc(v=vs.110).aspx

【温故知新】c#异步编程模型(APM)--使用委托进行异步编程的更多相关文章

  1. 转:[你必须知道的异步编程]——异步编程模型(APM)

    本专题概要: 引言 你知道APM吗? 你想知道如何使用异步编程模型编写代码吗? 使用委托也可以实现异步编程,你知道否? 小结 一.引言 在前面的C#基础知识系列中介绍了从C#1.0——C#4.0中一些 ...

  2. [你必须知道的异步编程]——异步编程模型(APM)

    本专题概要: 引言 你知道APM吗? 你想知道如何使用异步编程模型编写代码吗? 使用委托也可以实现异步编程,你知道否? 小结 一.引言 在前面的C#基础知识系列中 介绍了从C#1.0——C#4.0中一 ...

  3. 一、异步编程模型(APM)

    一.概念 APM即异步编程模式的简写(Asynchronous Programming Model).大家在写代码的时候或者查看.NET 的类库的时候肯定会经常看到和使用以BeginXXX和EndXX ...

  4. 异步编程模型(APM)模式

    什么是APM .net 1.0时期就提出的一种异步模式,并且基于IAsyncResult接口实现BeginXXX和EndXXX类似的方法. .net中有很多类实现了该模式(比如HttpWebReque ...

  5. 异步编程:IAsyncResult异步编程模型 (APM)

    http://www.cnblogs.com/heyuquan/archive/2013/03/22/2976420.html

  6. Asynchronous Programming Using Delegates使用委托进行异步编程

    http://msdn.microsoft.com/zh-cn/library/22t547yb(v=vs.110).aspx https://github.com/chucklu/Test/tree ...

  7. C#异步编程の-------异步编程模型(APM)

    术语解释: APM               异步编程模型, Asynchronous Programming Model EAP                基于事件的异步编程模式, Event ...

  8. .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)

    本文内容 异步编程类型 异步编程模型(APM) 参考资料 首先澄清,异步编程模式(Asynchronous Programming Patterns)与异步编程模型(Asynchronous Prog ...

  9. 【温故而知新-万花筒】C# 异步编程 逆变 协变 委托 事件 事件参数 迭代 线程、多线程、线程池、后台线程

    额基本脱离了2.0 3.5的时代了.在.net 4.0+ 时代.一切都是辣么简单! 参考文档: http://www.cnblogs.com/linzheng/archive/2012/04/11/2 ...

随机推荐

  1. 关于Web与JS

    Web包含的范围比较广, JS只是代码逻辑而已. Web比如HTTP Message, SOAP Message, 浏览器流程,工具等. 不仅仅是代码.

  2. datepicker,结束时间必须大于开始时间

    $('#js-start-time').datepicker({ dateFormat:'yy-mm-dd', onSelect: function( startDate ) { var $start ...

  3. WCF Service的Restfull风格

    怎样构建? •您需要什么样的资源? •将使用哪些 URI 表示这些资源? •每个 URI 将支持统一接口的哪些部件(HTTP 动词)?    URI的处理   •UriTemplate –System ...

  4. call by reference and copy/restore

    转自:http://stackoverflow.com/questions/8848402/whats-the-difference-between-call-by-reference-and-cop ...

  5. UVA 10497 - Sweet Child Makes Trouble 高精度DP

    Children are always sweet but they can sometimes make you feel bitter. In this problem, you will see ...

  6. 【Apache运维基础(5)】Apache的Rewrite攻略(2)

    简述 .htaccess文件(或者"分布式配置文件")提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录.作 ...

  7. iOS在线音乐播放SZKAVPlayer(基于AVPlayer的封装)

    由于最近闲着没事,想找有关在线音乐播放的demo学习一下,在gitHub跟code4APP上面查找了很多帖子,结果很多在线音乐都是基于AudioStream实现的,我感觉用起来不太方便.后来突然发现, ...

  8. iOS js oc相互调用(JavaScriptCore)(二)

    下来我们使用js调用iOS js调用iOS分两种情况 一,js里面直接调用方法 二,js里面通过对象调用方法 首先我们看第一种,直接调用方法. 其中用到了iOS的block 上代码 -(void)we ...

  9. ubuntu下搭建cocos2dx编程环境-中

        上篇文章里讲了在ubuntu下部署cocos2d-x开发环境,这篇文章主要示范在ubuntu下部署cocos2d-x android开发环境.分开写就是因为我看很多文章里都将这两件事情混杂着写 ...

  10. Python实现ssh批量登录并执行命令

    局域网内有一百多台电脑,全部都是linux操作系统,所有电脑配置相同,系统完全相同(包括用户名和密码),ip地址是自动分配的.现在有个任务是在这些电脑上执行某些命令,者说进行某些操作,比如安装某些软件 ...