当我们用到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. A beginner’s introduction to Deep Learning

    A beginner’s introduction to Deep Learning I am Samvita from the Business Team of HyperVerge. I join ...

  2. Codeforces Round #263 (Div. 2)

    吐槽:一辈子要在DIV 2混了. A,B,C都是简单题,看AC人数就知道了. A:如果我们定义数组为N*N的话就不用考虑边界了 #include<iostream> #include &l ...

  3. C# 对委托的BeginInvoke,EndInvoke 及Control 的BeginInvoke,EndInvoke 的理解

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  4. POJ 1401

    #include<iostream>using namespace std;int main(){    int num;    int i;    int sum;    cin> ...

  5. 使用Subversion进行版本控制

    使用Subversion进行版本控制 针对 Subversion 1.4(根据r2866编译) Ben Collins-Sussman Brian W. Fitzpatrick C. Michael  ...

  6. MySQL 5.1参考手册

    目录 前言 1. 一般信息 1.1. 关于本手册 1.2. 本手册采用的惯例 1.3. MySQL AB概述 1.4. MySQL数据库管理系统概述 1.4.1. MySQL的历史 1.4.2. My ...

  7. Win32应用程序中文支持

    Settings--Editor---Encoding改为Windows 936 main.cpp中#include "locale.h" winmain中增加一行: setloc ...

  8. MySQL 数据库存储引擎

    简单介绍 存储引擎就是指表的类型.数据库的存储引擎决定了表在计算机中的存储方式.存储引擎的概念是MySQl的特点,而且是一个插入式的存储引擎概念.这就决定了MySQl数据库中的表可以使用不同的存储方式 ...

  9. JAVA实现Excel导出数据(以写好的Excel模版导出)

    工作中经常会有将后台数据以Excel导出的功能. 简单的方法有将response的contentType设置为application/vnd.ms-excel: 或在JSP页面直接设置成: <% ...

  10. linux下如何查看和修改系统BLOCK的大小

    http://blog.163.com/drachen@126/blog/static/162607494201271435333906/ 查看os系统块的大小 [root]# /sbin/tune2 ...