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

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

相关文章

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

Python中高级文本模式匹配与查找技术指南

《Python中高级文本模式匹配与查找技术指南》文本处理是编程世界的永恒主题,而模式匹配则是文本处理的基石,本文将深度剖析PythonCookbook中的核心匹配技术,并结合实际工程案例展示其应用,希... 目录引言一、基础工具:字符串方法与序列匹配二、正则表达式:模式匹配的瑞士军刀2.1 re模块核心AP

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)

《MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)》本文给大家介绍MyBatis的xml中字符串类型判空与非字符串类型判空处理方式,本文给大家介绍的非常详细,对大家的学习或... 目录完整 Hutool 写法版本对比优化为什么status变成Long?为什么 price 没事?怎

C#异步编程ConfigureAwait的使用小结

《C#异步编程ConfigureAwait的使用小结》本文介绍了异步编程在GUI和服务器端应用的优势,详细的介绍了async和await的关键作用,通过实例解析了在UI线程正确使用await.Conf... 异步编程是并发的一种形式,它有两大好处:对于面向终端用户的GUI程序,提高了响应能力对于服务器端应

C#之枚举类型与随机数详解

《C#之枚举类型与随机数详解》文章讲解了枚举类型的定义与使用方法,包括在main外部声明枚举,用于表示游戏状态和周几状态,枚举值默认从0开始递增,也可手动设置初始值以生成随机数... 目录枚举类型1.定义枚举类型(main外)2.使用生成随机数总结枚举类型1.定义枚举类型(main外)enum 类型名字

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda