C# TAP异步编程(Task/async/await)总结

news/2025/7/9 5:06:04/

C#中有个很好用的东西,TAP异步编程(Task-based Asynchronous Pattern),是目前C#推荐的异步编程模型。它基于 System.Threading.Tasks.Task 和 async/await 关键字,旨在简化异步代码的编写、调试和维护。TAP 是现代 .NET 应用开发中最常用、最推荐的异步编程方式。
要实现TAP,有三个基本元素:Task、async和await。

  • Task: 表示一个异步操作,可能没有返回值(Task)或有返回值(Task<T>
  • async: 标记一个方法为异步
  • await: 用于等待一个异步操作完成,不会阻塞当前线程。

在Winform中,使用好TAP编程,可以方便的将异步回调操作变为同步,且不会阻塞UI线程! 非常优雅。

千问3给出的TAP优势:

特性说明
简化异步代码使用 async/await 避免了复杂的回调嵌套(回调地狱)。
线程友好不会阻塞主线程(如 UI 线程),提升用户体验。
异常处理统一异常可以通过 try/catch 捕获,不需要额外的错误回调。
取消支持支持通过 CancellationToken 安全取消异步操作。
上下文感知通过 SynchronizationContext 自动恢复执行上下文(如 UI 线程)

1.回调封装为异步

回调的关键是需要有key来识别是哪次调用!
通过TaskCompletionSource来封装回调执行时传输的结果数据。
通过await 一个Task实现阻塞等待。
基本代码如下:

public static class CallBackAsync{// 存储异步任务的上下文private static readonly ConcurrentDictionary<int, TaskCompletionSource<int>> _pendingTasks = new ConcurrentDictionary<int, TaskCompletionSource<int>>();// 回调中调用public static void OnCallBackAsync(int key, int result){if (_pendingTasks.TryRemove(key, out var tcs)){tcs.TrySetResult(result);//这里会激发await,并返回结果}}// 异步调用public static async Task<int> ChannelCtrlAsync(int key){var tcs = new TaskCompletionSource<int>();// 缓存任务上下文_pendingTasks[key] = tcs;// 调用原生同步方法int ret = NativeFunc(key);if (ret != 0){_pendingTasks.TryRemove(key, out _);tcs.TrySetException(new Exception($"{ret}")); //通过异常码返回错误!}return await tcs.Task; //关键点}// 原生方法public static int NativeFunc(int key){Console.WriteLine("NativeFunc");//异常情况//return -1;//线程中模拟回调Task.Run(() =>{OnCallBackAsync(1, 99);});return 0;}}

这里用ConcurrentDictionary字典封装了key和TaskCompletionSource的上下文信息,异步调用时要创建一份,回调时进行查找并删除。
注意当原生调用立即返回错误且不进回调时,产生的错误码没法通过TaskCompletionSource传出,此时可通过异常机制来输出。

按钮调用的实现:

private async void button1_Click(object sender, EventArgs e) //必须async标记{try{var result = await CallBackAsync.ChannelCtrlAsync(1).ConfigureAwait(true); // 恢复UI上下文//继续干其他事情,UI不会阻塞}catch (Exception ex){//表示底层调用直接返回了错误码Console.WriteLine($"底层直接返回,返回值:{ex.Message}");}}

2.阻塞调用封装

此时无需TaskCompletionSource去手动等待,比如串口的阻塞式异步:

public async Task SendDataAsync(string strText){return await Task.Run(() =>{m_Port.Write(strText);});}

3.任务取消

通过传入参数CancellationTokenSource 对象,可以在外部调用Cancel()方法取消任务。

public async Task SendXXXAsync(string strText, CancellationTokenSource cts){return await Task.Run(() =>{while(1){if (cts != null && cts.Token.IsCancellationRequested){return;}m_Port.Write(部分数据); //循环发送使用}});}

4.超时处理

var timeoutTask = Task.Delay(TimeSpan.FromSeconds(3));
var completedTask = await Task.WhenAny(task, timeoutTask);
if (completedTask == timeoutTask)
{// 超时处理逻辑tcs.TrySetException(new Exception("ERR_CTRL_TIMEOUT")); //通过异常码返回错误!
}
return await tcs.Task;

http://www.ppmy.cn/news/1739441.html

相关文章

centos6.5 老旧系统编译glib-2.58.3.tar.bz2

glib编译依赖python3 meson ninja libffi libmount python3我用的 python3.13.tar.gz&#xff0c;安装meson用python3 编译产生的pip3, 由于python3编译没有安装openssl&#xff0c;导致pip3 无法下载 openssl至少1.1.1版本&#xff0c;我用openssl-1.1.1w.tar.gz 配置pyt…

关于mybatis插入大批量数据效率问题

一、即便分批次用mybatis插入数据&#xff0c;效率依旧不高&#xff0c;原因&#xff1a; MyBatis一次性批量插入几千条数据&#xff0c;为什么性能很差&#xff1f;-腾讯云开发者社区-腾讯云 文中提出&#xff1a; 默认执行器类型为Simple&#xff0c;会为每个语句创建一个新…

slam--非线性优化

教程 非线性优化 slam的状态估计问题。 状态估计问题的方法大致分成两种 增量和批量。 增量法 核心思想 逐步更新状态&#xff1a;每次接收到新的观测数据时&#xff0c;立即更新当前状态的估计&#xff08;如机器人位姿、地图点&#xff09;&#xff0c;保持一个动态的“状…

触觉智能RK3576核心板工业应用之软硬件全国产化,成功适配开源鸿蒙OpenHarmony5.0

在全球科技竞争加剧和供应链安全日益重要的背景下&#xff0c;实现关键软硬件的全国产化替代已成为国家战略和产业共识。在这一背景下&#xff0c;触觉智能推出RK3576核心板,率先适配开源鸿蒙OpenHarmony5.0操作系统&#xff0c;真正实现了从芯片到操作系统的全栈国产化方案&am…

linux 安装 opencv源码4.5.4记录

1、解压下载的opencv源码包 unzip ~/package/opencv-4.5.4.zip2、进入源码 cd ~/package/opencv-4.5.43、创建或清空 build 目录 rm -rf build mkdir build cd build4、cmake 配置阶段启用 pkg-config 支持进行配置 其他教程当安装到最后一步&#xff0c;测试有没有安装成功…

时差定位、频差定位与差分多普勒定位的联系与区别

三种定位技术都属于无源定位方法&#xff0c;核心思想是通过测量目标信号到达不同接收站&#xff08;传感器&#xff09;的差异来确定目标位置。它们都依赖于多个接收站之间的协作测量。下面详细阐述它们的联系与区别&#xff1a; 1. 基本概念 时差定位 (Time Difference of A…

【洛杉矶实况】这里正在发生什么?

始于1996年的Cine Gear聚焦专业电影器材&#xff0c;每年都能吸引大量来自好莱坞以及全球电影制作群体&#xff0c;这里也成了全球电影科技最前沿的风向标。 今年6月6号-7号&#xff0c;CineGear在洛杉矶环球影城片场火爆开场&#xff0c;各器材展商沿路两边一字排开&#xff0…

1.ES介绍

ES 是一个海量搜索引擎&#xff0c;可以从海量数据中快速找到需要的内容。 应用于日志分析、实时监控等领域。 ES结合Kibana,Logstash,Beats elastic stack (ELK) ES的底层实现是Lucene技术 Lucene是java语言的搜索引擎类库。 ES功能更强大&#xff0c;支持分布式&#xf…