异步编程

  • 同步编程,请求响应模型,同步化、顺序化、事务化。
  • 异步编程,事件驱动模型,以 Fire and Forget 方式实现。

异步编程模式

-§- 异步编程模型 (APM) 模式: IAsyncResult 模式,异步操作需要 Begin 和 End 方法;
-§- 基于事件的异步模式(EAP):事件、事件处理程序委托类型和 EventArg 派生类型;
-§- 基于任务的异步模式(TAP):推荐模式,.NET Framework 4 引入,基于 System.Threading.Tasks 命名空间,利用一种方法表示异步操作的启动和完成;

类 LogicalMethodInfo 提供 Invoke 和 BeginInvoke 方法支持同步或异步执行委托的方法:

 public sealed class System.Web.Services.Protocols.LogicalMethodInfo{
public object[] Invoke(object target, object[] values);
public IAsyncResult BeginInvoke(object target, object[] values, AsyncCallback callback, object asyncState);
public object[] EndInvoke(object target, IAsyncResult asyncResult);
}

其中,target 是委托方法所属的类实例,values 是委托方法的参数列表。

异步方法调用模式

三种方法 调用模式区别:原线程获取异步线程已经完成的消息的方式。

其中,BeginInvoke 方法用于启动异步调用,EndInvoke 方法用于检索并获取异步调用结果然后释放线程占用的资源。BeginInvoke 立即返回,不等待异步方法调用完成,同时在调用时创建一个 AsyncResult 类对象,但是 BeginInvoke 返回 IAsyncResult 接口的引用,可用于监视异步方法的调用进度,调用 BeginInvoke 后可随时调用 EndInvoke 方法。

其中,IAsyncResult 接口 的 AsyncState 属性获取 Object 类型的对象可以作为 BeginInvoke 方法调用时的 State 参数(可根据需要自定义)。 委托定义和异步委托方法定义为:

 public delegate int MyDel(string str);
public static int DelFun(string str){
   Console.WriteLine("异步线程执行方法:DelFun() in " + Thread.CurrentThread.ManagedThreadId);
   Thread.Sleep(3000);
   return str.Length;
}

:BeginInvoke 的参数是在编译时根据委托的定义动态生成的,前面参数的个数和类型与委托定义中的参数个数和类型相同,后两个参数分别是 AsyncCallback 和 Object 类型。BeginInvoke 的调用者的方法列表有且只能有一个方法。BeginInvoke 第三个参数可为任意类型,最终都可通过 AsyncState 属性获得对应值。

等待模式 Waiting-Until-Done  

如果异步方法调用未完成,EndInvoke 将一直阻塞到异步方法调用完成才执行。其中,等待 WaitHandle 是一项常用的线程同步技术,可以通过 BeginInvoke 返回的 IAsyncResult 的 AsyncWaitHandle 属性调用 WaitOne() 方法阻止当前线程,直到获取到异步方法调用完成时发出的 WaitHandle 信号。

 public static void AsyncWaitingTest()
{
   MyDel myDel = new MyDel(TestClass.DelFun);    Console.WriteLine("主线程:AsyncWaitingTest() in " + Thread.CurrentThread.ManagedThreadId);
   IAsyncResult iar = myDel.BeginInvoke("sqh", null, null);
   Console.WriteLine("主线程继续执行... in " + Thread.CurrentThread.ManagedThreadId);    while (!iar.AsyncWaitHandle.WaitOne(1000)){
      Console.WriteLine("Waiting... AsyncMethod()");
   }
   int strLen = myDel.EndInvoke(iar);
   Console.WriteLine("Str Length:{0}", strLen);
}

轮询模式 Polling  

利用 BeginInvoke 返回的 IAsyncResult 的 IsCompleted 属性来判断异步方法调用是否完成。

 public static void AsyncPollingTest()
{
   MyDel myDel = new MyDel(TestClass.DelFun);    Console.WriteLine("主线程:AsyncPollingTest() in " + Thread.CurrentThread.ManagedThreadId);
   IAsyncResult iar = myDel.BeginInvoke("sqh", null, null);
   Console.WriteLine("主线程继续执行... in " + Thread.CurrentThread.ManagedThreadId);    while (!iar.IsCompleted){
      Thread.Sleep(1000);
      Console.WriteLine("Waiting... AsyncMethod()");
   }
   int strLen = myDel.EndInvoke(iar);
   Console.WriteLine("Str Length:{0}", strLen);
}

回调模式 Callback  

调用 BeginInvoke 时提供回调方法,异步方法调用结束后,回调方法在 ThreadPool 中的异步线程上自动执行,并调用 EndInvoke 方法。
回调方法形如:void AsyncCallback(IAsyncResult iar);

 public static void AsyncCallbackTest()
{
   MyDel myDel = new MyDel(TestClass.DelFun);    Console.WriteLine("主线程:AsyncCallbackTest() in " + Thread.CurrentThread.ManagedThreadId);
   IAsyncResult iar = myDel.BeginInvoke("sqh", CallbackMethod, myDel);
   Console.WriteLine("主线程继续执行... in " + Thread.CurrentThread.ManagedThreadId);
   // ... 其他操作,独立于异步线程
}
public static void CallbackMethod(IAsyncResult iar)
{
   Console.WriteLine("异步方法执行完毕,开始执行回调方法 in " + Thread.CurrentThread.ManagedThreadId);    //AsyncResult ar = (AsyncResult)iar; // **推荐**
   //MyDel myDel = (MyDel)ar.AsyncDelegate;
   MyDel myDel = (MyDel)iar.AsyncState; // 这种调用方式 BeginInvoke 需要 myDel 参数    int result = myDel.EndInvoke(iar);
   Console.WriteLine(result);
}

其他:当委托的方法列表中有多个方法时,可以利用 GetInvocationList() 方法得到 Delegate[] 数组,然后依次调用 BeginInvoke 方法,不同的方法在线程池的不同线程上运行!
[1]. 异步编程模式系列(1-6)
[2]. 异步方法调用模式总结异步调用四种方法

async/await

几点共识

  • async和await共存
  • async/await均不会立即发起新线程,直至遇到真正的异步方法(Task)
  • await用于打分裂点,程序遇到await直接返回,异步任务完成后再执行await后的代码
// qq  ww  异步方法完成, 返回结果:GoCostThings
Console.WriteLine("qq");
var ret = FuncAsync();
Console.WriteLine("ww"); public static async Task<string> FuncAsync() {
var document = await GoCostThings();
Console.WriteLine("异步方法完成, 返回结果:" + document);
return document;
}
public static Task<string> GoCostThings() {
var task = Task.Run(() => {
Thread.Sleep(3000);
return "GoCostThings";
});
return task;
}

参考示例

C# - 多线程 之 异步编程的更多相关文章

  1. 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换

    [源码下载] 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换 作者:webabcd 介绍 ...

  2. 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress

    [源码下载] 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithPro ...

  3. 初步谈谈 C# 多线程、异步编程与并发服务器

    多线程与异步编程可以达到避免调用线程异步阻塞作用,但是两者还是有点不同. 多线程与异步编程的异同: 1.线程是cpu 调度资源和分配的基本单位,本质上是进程中的一段并发执行的代码. 2.线程编程的思维 ...

  4. C++多线程并发---异步编程

    线程同步主要是为了解决对共享数据的竞争访问问题,所以线程同步主要是对共享数据的访问同步化(按照既定的先后次序,一个访问需要阻塞等待前一个访问完成后才能开始).这篇文章谈到的异步编程主要是针对任务或线程 ...

  5. 多线程之异步编程: 经典和最新的异步编程模型,async与await

    经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...

  6. 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换

    经典的异步编程模型(IAsyncResult) 最新的异步编程模型(async 和 await) 将 IAsyncInfo 转换成 Task 将 Task 转换成 IAsyncInfo 示例1.使用经 ...

  7. C#多线程之异步编程

    c#中异步编程,主要有两种方法: 1.委托的异步调用: 2.Task的await,async (c# 4.5) 我们来看例子: /// <summary> /// 异步保存网页,url:网 ...

  8. c# 中的多线程和异步

    前言: 1.异步和多线程有区别吗? 答案:多线程可以说是实现异步的一种方法方法,两者的共同目的:使主线程保持对用户操作的实时响应,如点击.拖拽.输入字符等.使主程序看起来实时都保持着等待用户响应的状态 ...

  9. Async await 异步编程说明

    希望在编程上有些许提高所以 最近连续2篇博客都在说明多线程和异步编程的使用,异步和多线程之间区别请自行百度,因为理解不是特别透彻就不在叙述以免误导大家,这里写下新研究整理 task  和 await ...

随机推荐

  1. Java compiler level does not match解决方法

    从别的地方导入一个项目的时候,经常会遇到eclipse/Myeclipse报Description  Resource Path Location Type Java compiler level d ...

  2. transient关键字的用法

    本篇博客转自 一直在路上 Java transient关键字使用小记 1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java ...

  3. 我将系统从Windows迁移至Linux下的点点滴滴

    一.写在最前 由于本人的技术水平有限,难免会出现错误.本文对任何一个人有帮助都是我莫大的荣幸,任何一个大神对我的点拨,我都会感激不尽. 二.技术选型 在2013年8月低的时候,公司中了XXX市场监督局 ...

  4. 使用ENode框架前您需要了解的东西(初稿)

    选择ENode意味着什么可能很多人还不太清楚.我简单整理了一下: 意味着你选择了:你需要做DDD领域建模.选择了事件驱动的架构.选择了CQRS架构.选择了最终一致性.选择了事件溯源.选择了分布式.这些 ...

  5. WPF - 属性系统 (2 of 4)

    属性更改回调 前一章的示例中,对各个参数的设置都非常容易理解.如果我们仅仅需要创建一个独立的依赖项属性,那么上面所提到的创建依赖项属性的基础知识足以满足需求.但是事情往往并非如此完美.在一个系统中,很 ...

  6. 快速web开发中的前后端框架选型最佳实践

    这个最佳实践是我目前人在做的一个站点,主要功能: oauth登录 发布文章(我称为"片段"),片段可以自定义一些和内容有关的指标,如“文中人物:12”.支持自定义排版.插图.建立相 ...

  7. The Coroutine

    关于Coroutine 说到coroutine就不的不说subroutine,也就是我们常用到的一般函数.调用一个函数开始执行,然后函数执行完成后就退出,再次调用的时候,再从头开始,调用之间是没有保存 ...

  8. 浅谈WebService的版本兼容性设计

    在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...

  9. 单选按钮加confirm进行判断返回false任被选中问题

    <html> <head> <script language="javascript"> var checkValue = "&quo ...

  10. 微软MVP攻略 (如何成为MVP?一个SQL Server MVP的经验之谈)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 初衷 什么是微软MVP? 成为微软MVP的条件? 如何成为微软MVP? (一) 申请时间划分 (二) 前期准备 (三) ...