【微软技术栈】与其他异步模式和类型互操作

2023-11-25 18:45

本文主要是介绍【微软技术栈】与其他异步模式和类型互操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文内容

  1. 任务和异步编程模型 (APM)
  2. 任务和基于事件的异步模式 (EAP)
  3. 任务和等待句柄

.NET 中异步模式的简短历史记录:

  • .NET Framework 1.0 引进了 IAsyncResult 模式,也称为异步编程模型 (APM) 或 Begin/End 模式。
  • .NET Framework 2.0 增加了基于事件的异步模式 (EAP)。
  • .NET Framework 4 引进了基于任务的异步模式 (TAP),它取代了 APM 和 EAP,并能够轻松构建从早期模式中迁移的例程。

1、任务和异步编程模型 (APM)

1.1 从 APM 到 TAP

因为异步编程模型 (APM) 模式的结构合理,而且能够轻松生成包装,将 APM 实现公开为 TAP 实现。 .NET Framework 4 及更高版本包含采用 FromAsync 方法重载形式的帮助器例程来实现这种转换。

请考虑 Stream 类及其 BeginRead 和 EndRead 方法,它们代表与同步 Read 方法对应的 APM:

public int Read(byte[] buffer, int offset, int count)
public IAsyncResult BeginRead(byte[] buffer, int offset,int count, AsyncCallback callback,object state)
public int EndRead(IAsyncResult asyncResult)

可以使用 TaskFactory<TResult>.FromAsync 方法来实现此操作的 TAP 包装,如下所示:

public static Task<int> ReadAsync(this Stream stream,byte[] buffer, int offset,int count)
{if (stream == null)throw new ArgumentNullException("stream");return Task<int>.Factory.FromAsync(stream.BeginRead,stream.EndRead, buffer,offset, count, null);
}

此实现类似于以下内容:

 public static Task<int> ReadAsync(this Stream stream,byte [] buffer, int offset,int count){if (stream == null)throw new ArgumentNullException("stream");var tcs = new TaskCompletionSource<int>();stream.BeginRead(buffer, offset, count, iar =>{try {tcs.TrySetResult(stream.EndRead(iar));}catch(OperationCanceledException) {tcs.TrySetCanceled();}catch(Exception exc) {tcs.TrySetException(exc);}}, null);return tcs.Task;
}

1.2 从 TAP 到 APM

如果现有的基础结构需要 APM 模式,则还需要采用 TAP 实现并在需要 APM 实现的地方使用它。 由于任务可以组合,并且 Task 类实现 IAsyncResult,你可以使用一个简单的 helper 函数执行此操作。 以下代码使用 Task<TResult> 类的扩展,但可以对非泛型任务使用几乎相同的函数。

public static IAsyncResult AsApm<T>(this Task<T> task,AsyncCallback callback,object state)
{if (task == null)throw new ArgumentNullException("task");var tcs = new TaskCompletionSource<T>(state);task.ContinueWith(t =>{if (t.IsFaulted)tcs.TrySetException(t.Exception.InnerExceptions);else if (t.IsCanceled)tcs.TrySetCanceled();elsetcs.TrySetResult(t.Result);if (callback != null)callback(tcs.Task);}, TaskScheduler.Default);return tcs.Task;
}

现在,请考虑具有以下 TAP 实现的用例:

public static Task<String> DownloadStringAsync(Uri url)

并且想要提供此 APM 实现:

public IAsyncResult BeginDownloadString(Uri url,AsyncCallback callback,object state)
public string EndDownloadString(IAsyncResult asyncResult)

以下示例演示了一种向 APM 迁移的方法:

public IAsyncResult BeginDownloadString(Uri url,AsyncCallback callback,object state)
{return DownloadStringAsync(url).AsApm(callback, state);
}public string EndDownloadString(IAsyncResult asyncResult)
{return ((Task<string>)asyncResult).Result;
}

2、任务和等待句柄

2.1 从等待句柄到 TAP

虽然等待句柄不能实现异步模式,但高级开发人员可以在设置等待句柄时使用 WaitHandle 类和 ThreadPool.RegisterWaitForSingleObject 方法实现异步通知。 可以包装 RegisterWaitForSingleObject 方法以在等待句柄中启用针对任何同步等待的基于任务的替代方法:

public static Task WaitOneAsync(this WaitHandle waitHandle)
{if (waitHandle == null)throw new ArgumentNullException("waitHandle");var tcs = new TaskCompletionSource<bool>();var rwh = ThreadPool.RegisterWaitForSingleObject(waitHandle,delegate { tcs.TrySetResult(true); }, null, -1, true);var t = tcs.Task;t.ContinueWith( (antecedent) => rwh.Unregister(null));return t;
}

使用此方法,可以在异步方法中使用现有 WaitHandle 实现。 例如,若要限制在任何特定时间执行的异步操作数,可以利用信号灯(System.Threading.SemaphoreSlim 对象)。 可以将并发运行的操作数目限制到 N,方法为:初始化到 N 的信号量的数目、在想要执行操作时等待信号量,并在完成操作时释放信号量 :

static int N = 3;static SemaphoreSlim m_throttle = new SemaphoreSlim(N, N);static async Task DoOperation()
{await m_throttle.WaitAsync();// do workm_throttle.Release();
}

还可以构建不依赖等待句柄就完全可以处理任务的异步信号量。 若要执行此操作,可以使用 使用基于任务的异步模式 中所述的用于在 Task。

2.2 从 TAP 到等待句柄

正如前面所述, Task 类实现 IAsyncResult,且该实现公开 IAsyncResult.AsyncWaitHandle 属性,该属性会返回在 Task 完成时设置的等待句柄。 可以获得 WaitHandle 的 Task ,如下所示:

WaitHandle wh = ((IAsyncResult)task).AsyncWaitHandle;

这篇关于【微软技术栈】与其他异步模式和类型互操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/424369

相关文章

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

Java中的登录技术保姆级详细教程

《Java中的登录技术保姆级详细教程》:本文主要介绍Java中登录技术保姆级详细教程的相关资料,在Java中我们可以使用各种技术和框架来实现这些功能,文中通过代码介绍的非常详细,需要的朋友可以参考... 目录1.登录思路2.登录标记1.会话技术2.会话跟踪1.Cookie技术2.Session技术3.令牌技

RabbitMQ工作模式中的RPC通信模式详解

《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

Web技术与Nginx网站环境部署教程

《Web技术与Nginx网站环境部署教程》:本文主要介绍Web技术与Nginx网站环境部署教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Web基础1.域名系统DNS2.Hosts文件3.DNS4.域名注册二.网页与html1.网页概述2.HTML概述3.

SQL Server身份验证模式步骤和示例代码

《SQLServer身份验证模式步骤和示例代码》SQLServer是一个广泛使用的关系数据库管理系统,通常使用两种身份验证模式:Windows身份验证和SQLServer身份验证,本文将详细介绍身份... 目录身份验证方式的概念更改身份验证方式的步骤方法一:使用SQL Server Management S

Java使用WebView实现桌面程序的技术指南

《Java使用WebView实现桌面程序的技术指南》在现代软件开发中,许多应用需要在桌面程序中嵌入Web页面,例如,你可能需要在Java桌面应用中嵌入一部分Web前端,或者加载一个HTML5界面以增强... 目录1、简述2、WebView 特点3、搭建 WebView 示例3.1 添加 JavaFX 依赖3

Redis高可用-主从复制、哨兵模式与集群模式详解

《Redis高可用-主从复制、哨兵模式与集群模式详解》:本文主要介绍Redis高可用-主从复制、哨兵模式与集群模式的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录Redis高可用-主从复制、哨兵模式与集群模式概要一、主从复制(Master-Slave Repli

Python 异步编程 asyncio简介及基本用法

《Python异步编程asyncio简介及基本用法》asyncio是Python的一个库,用于编写并发代码,使用协程、任务和Futures来处理I/O密集型和高延迟操作,本文给大家介绍Python... 目录1、asyncio是什么IO密集型任务特征2、怎么用1、基本用法2、关键字 async1、async

嵌入式Linux驱动中的异步通知机制详解

《嵌入式Linux驱动中的异步通知机制详解》:本文主要介绍嵌入式Linux驱动中的异步通知机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、异步通知的核心概念1. 什么是异步通知2. 异步通知的关键组件二、异步通知的实现原理三、代码示例分析1. 设备结构

一文带你搞懂Redis Stream的6种消息处理模式

《一文带你搞懂RedisStream的6种消息处理模式》Redis5.0版本引入的Stream数据类型,为Redis生态带来了强大而灵活的消息队列功能,本文将为大家详细介绍RedisStream的6... 目录1. 简单消费模式(Simple Consumption)基本概念核心命令实现示例使用场景优缺点2