当前位置: 首页 > article >正文

别再只用Task.Run了!用TaskCompletionSource在C#里优雅地控制异步流程(附真实支付场景代码)

用TaskCompletionSource重构C#异步支付流程从回调地狱到优雅编排在电商支付这类多步骤异步操作中我们常常遇到这样的困境库存检查、支付网关调用、订单状态更新等操作存在严格的先后依赖关系而传统的Task.Run或Task.Wait要么导致线程阻塞要么陷入回调地狱。最近在重构公司支付系统时我发现TaskCompletionSource以下简称TCS能完美解决这些问题——它就像异步世界的交通信号灯精确控制每个任务的执行时机。1. 为什么Task.Run在支付场景中力不从心假设我们要实现一个火车票支付流程用户选票→跳转支付→支付成功→更新订单状态。用Task.Run的典型实现会是这样// 典型的问题实现 Task.Run(async () { var ticket await SelectTicketAsync(); var paymentResult await PayAsync(ticket); await UpdateOrderAsync(paymentResult); }).Wait(); // 这里阻塞了调用线程这种写法有三个致命缺陷线程浪费Wait()会阻塞调用线程而异步操作本可释放线程错误处理困难整个链路只有一个顶层的异常捕获点无法灵活控制如果想在支付成功后插入一个短信通知必须修改主流程代码更糟糕的是当需要处理第三方支付回调时代码会变成这样// 回调地狱的雏形 PayAsync(ticket).ContinueWith(paymentTask { UpdateOrderAsync(paymentTask.Result).ContinueWith(updateTask { SendSmsAsync(updateTask.Result).ContinueWith(...); }); });2. TaskCompletionSource的核心优势TCS本质上是一个任务控制器它提供三个关键能力手动控制任务生命周期通过SetResult/SetException主动决定任务何时完成跨方法协调能力TCS实例可以传递让不同方法协同控制同一个任务无阻塞等待通过Task属性获取可await的任务对象对比传统方式特性Task.RunTaskCompletionSource线程占用占用线程池线程零线程占用流程控制线性执行任意拓扑结构回调处理需嵌套ContinueWith扁平化的await链异常传播单一路径多路径集中处理3. 支付流程的重构实战让我们用TCS重构完整的票务支付流程包含以下阶段选票服务返回票务信息支付服务处理支付第三方支付回调验证订单服务更新状态通知服务发送确认3.1 定义流程协调器首先创建支付流程的协调器public class PaymentOrchestrator { private readonly TaskCompletionSourceTicketInfo _ticketTcs new(); private readonly TaskCompletionSourcePaymentResult _paymentTcs new(); private readonly TaskCompletionSourcebool _callbackTcs new(); public TaskTicketInfo TicketTask _ticketTcs.Task; public TaskPaymentResult PaymentTask _paymentTcs.Task; public Taskbool CallbackVerifiedTask _callbackTcs.Task; public void CompleteTicketSelection(TicketInfo ticket) _ticketTcs.TrySetResult(ticket); public void CompletePayment(PaymentResult result) _paymentTcs.TrySetResult(result); public void VerifyCallback(bool isValid) _callbackTcs.TrySetResult(isValid); }3.2 实现主流程现在可以编写清晰的主流程public async TaskOrderResult ProcessPaymentAsync() { var orchestrator new PaymentOrchestrator(); // 启动并行操作 var selectTask SelectTicketAsync(orchestrator); var payTask ProcessPaymentAsync(orchestrator); var callbackTask HandleCallbackAsync(orchestrator); try { // 按顺序协调各阶段 var ticket await orchestrator.TicketTask; var payment await orchestrator.PaymentTask; var isValid await orchestrator.CallbackVerifiedTask; if(!isValid) throw new InvalidOperationException(回调验证失败); var order await UpdateOrderAsync(payment); await SendConfirmationAsync(order); return order; } catch(Exception ex) { orchestrator.CancelAll(ex); // 自定义的取消逻辑 throw; } }3.3 处理支付回调回调处理变得异常简洁// 支付网关回调接口 [HttpPost] public async TaskIActionResult PaymentCallback([FromBody] CallbackRequest request) { var isValid VerifySignature(request); // 通过DI获取之前创建的orchestrator实例 _orchestrator.VerifyCallback(isValid); return Ok(); }4. 高级应用模式4.1 超时控制为TCS添加超时能力public static async TaskT WithTimeoutT(this TaskT task, TimeSpan timeout) { var delayTask Task.Delay(timeout); var completedTask await Task.WhenAny(task, delayTask); if(completedTask delayTask) throw new TimeoutException(); return await task; } // 使用方式 try { var payment await orchestrator.PaymentTask.WithTimeout(TimeSpan.FromSeconds(30)); } catch(TimeoutException) { // 处理超时 }4.2 批量操作协调处理批量支付时可以用WhenAll组合多个TCSvar tcsList payments.Select(p new TaskCompletionSourcePaymentResult()).ToList(); // 每个支付完成时 void OnPaymentComplete(Guid paymentId, Result result) { var tcs tcsList.First(x x.PaymentId paymentId); tcs.SetResult(result); } // 等待所有支付完成 var results await Task.WhenAll(tcsList.Select(t t.Task));5. 性能对比与最佳实践在负载测试中TCS方案相比传统方式展现出显著优势指标Task.Run方案TCS方案线程切换次数142次/秒23次/秒内存分配45MB12MB99%延迟328ms156ms最佳实践建议生命周期管理为长时间运行的TCS实现IDisposable避免内存泄漏错误传播总是通过TrySetException而不是SetException避免竞态条件取消支持结合CancellationToken实现优雅终止避免滥用简单场景直接用async/await更合适// 带取消支持的实现示例 public async Task ProcessWithCancellationAsync(CancellationToken ct) { var tcs new TaskCompletionSourcebool(); using(ct.Register(() tcs.TrySetCanceled())) { await tcs.Task; } }在最近一次电商大促中这套基于TCS的支付系统平稳处理了每秒1200的支付请求而之前的回调方案在400请求时就出现了线程池耗尽的问题。更难得的是当需要添加新的风控检查步骤时只需在协调器中插入一个新的TCS节点完全不用修改主流程逻辑。

相关文章:

别再只用Task.Run了!用TaskCompletionSource在C#里优雅地控制异步流程(附真实支付场景代码)

用TaskCompletionSource重构C#异步支付流程:从回调地狱到优雅编排 在电商支付这类多步骤异步操作中,我们常常遇到这样的困境:库存检查、支付网关调用、订单状态更新等操作存在严格的先后依赖关系,而传统的Task.Run或Task.Wait要么…...

爬虫党必看:实测6个免费代理网站,手把手教你筛选出最快最稳的IP

高效数据采集实战:6大免费代理源测评与智能筛选方案 在数据采集领域,代理IP的质量直接影响着爬虫的稳定性和效率。面对市场上众多的免费代理源,如何快速识别可用资源并建立有效的筛选机制,成为每位数据工程师的必备技能。本文将基…...

如何3步轻松下载B站大会员4K视频:你的个人高清资源库搭建指南

如何3步轻松下载B站大会员4K视频:你的个人高清资源库搭建指南 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 你是否遇到过…...

基础模型如何革新科研工作流与科学发现

1. 基础模型与科学发现的范式转移 实验室里的显微镜旁堆满了未标记的样本,隔壁工作站正在训练第37版蛋白质结构预测模型。三年前需要博士生团队半年才能完成的文献综述,现在GPT-4用20分钟就能生成初步框架。这不是科幻场景,而是我最近在生物医…...

别再只调参了!深入CPO的‘循环种群减少’策略,帮你跳出局部最优陷阱

冠豪猪优化算法(CPO)的防御策略与工程实践:从理论到代码实现 在解决复杂工程优化问题时,传统算法常常面临收敛速度慢和易陷入局部最优的双重困境。2024年提出的冠豪猪优化算法(Crested Porcupine Optimizer, CPO)通过模拟自然界中冠豪猪的防御行为&#…...

歌词滚动姬:零基础也能制作专业LRC歌词的终极指南

歌词滚动姬:零基础也能制作专业LRC歌词的终极指南 【免费下载链接】lrc-maker 歌词滚动姬|可能是你所能见到的最好用的歌词制作工具 项目地址: https://gitcode.com/gh_mirrors/lr/lrc-maker 还在为制作精准的歌词时间轴而烦恼吗?歌词…...

告别官方代码!手把手教你为YOLOv8-Seg模型定制ONNX导出,适配RKNN/Horizon/TensorRT部署

深度定制YOLOv8-Seg模型:从PyTorch到边缘计算芯片的高效部署指南 在计算机视觉领域,实时语义分割一直是工业应用中的关键技术挑战。YOLOv8-Seg作为最新一代的实时分割网络,其性能与效率平衡令人印象深刻。然而,当我们需要将其部署…...

Zephyr驱动初始化顺序详解:你的驱动为什么没跑起来?从链接脚本到启动流程的深度排错

Zephyr驱动初始化顺序详解:从链接脚本到启动流程的深度排错 当你在Zephyr RTOS中开发自定义驱动程序时,是否遇到过这样的场景:精心编写的驱动代码在运行时毫无反应,或者系统在启动阶段就崩溃?这往往与驱动初始化顺序的…...

Windows Cleaner:终极免费的Windows系统清理工具,一键解决C盘爆满问题

Windows Cleaner:终极免费的Windows系统清理工具,一键解决C盘爆满问题 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服! 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 你是否经历过这样的…...

别再只盯着SENet了!用PyTorch手把手实现CBAM注意力模块(附完整代码与可视化)

从零实现CBAM注意力模块:PyTorch实战与可视化对比 在计算机视觉领域,注意力机制已经成为提升模型性能的关键技术。虽然SENet通过通道注意力取得了显著效果,但CBAM(Convolutional Block Attention Module)更进一步&…...

在 Node.js 服务中集成 Taotoken 实现稳定 AI 功能调用

在 Node.js 服务中集成 Taotoken 实现稳定 AI 功能调用 1. 环境准备与基础配置 在 Node.js 服务中集成 Taotoken 的第一步是完成基础环境配置。建议将 API Key 存储在环境变量中而非硬编码,这既符合安全规范也便于多环境部署。在项目根目录创建 .env 文件并添加以…...

避开FANUC机器人后台编程的坑:DO状态输出程序组掩码设置与常见错误

FANUC机器人后台编程实战:DO信号输出与组掩码深度解析 在工业自动化领域,FANUC机器人以其稳定性和灵活性著称,而后台程序(Background Logic)作为其重要功能之一,常被用于实时监控和状态输出。然而,许多工程师在实际开发…...

如何快速配置NBFC-Linux:笔记本电脑风扇控制终极指南

如何快速配置NBFC-Linux:笔记本电脑风扇控制终极指南 【免费下载链接】nbfc-linux NoteBook FanControl ported to Linux 项目地址: https://gitcode.com/gh_mirrors/nb/nbfc-linux NBFC-Linux是一款专为Linux系统设计的笔记本电脑风扇控制工具,能…...

一个标准 Java SpringBoot 项目 Git ignore 文件

一个标准 Java SpringBoot 项目 Git ignore 文件 target/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/ .kotlin### IntelliJ IDEA ### .idea/modules.xml .idea/jarRepositories.xml .idea/compiler.xml .idea/libraries/ *.iws *.iml *…...

cn-daily-tools:专为中文开发者打造的高效本土化工具库

1. 项目概述:一个中文开发者的日常工具箱如果你是一个经常在GitHub上寻找轮子的中文开发者,大概率会和我有一样的感受:很多优秀的工具库是英文的,文档是英文的,社区讨论也是英文的。这当然没问题,开源无国界…...

NCP1611/NCP1612 PFC控制器CCFF技术与应用解析

1. NCP1611/NCP1612 PFC控制器核心特性解析 NCP1611和NCP1612是安森美半导体推出的高性能功率因数校正(PFC)控制器,采用创新的电流控制频率回退(CCFF)技术。这两款器件在开关电源设计中扮演着关键角色,特别是在需要高功率因数(>0.99)和低总谐波失真(T…...

Transformer如何预测全国空气质量?AirFormer论文核心思想与代码复现指北

Transformer在空气质量预测中的革命性突破:AirFormer架构解析与实战指南 1. 时空预测的新范式:当Transformer遇见环境科学 2017年Transformer架构的横空出世彻底改变了自然语言处理领域的游戏规则,而如今这一革命性技术正在环境科学领域掀起新…...

PX4飞控固件里那些配置文件都是干啥的?从default.px4board到rc.board_sensors的保姆级解读

PX4飞控固件配置文件全景解析:从硬件抽象到传感器启动的完整链路 当你第一次打开PX4飞控的代码仓库,面对数十个配置文件和嵌套的目录结构时,那种扑面而来的压迫感我至今记忆犹新。作为开源飞控领域的标杆,PX4的强大之处在于其模块…...

避坑指南:在银河麒麟V10桌面版安装Qt 5.12.10时,如何解决权限卡死和图标不见的问题?

银河麒麟V10桌面版Qt 5.12.10安装避坑实战:权限管理与图标修复全解析 第一次在银河麒麟V10上安装Qt 5.12.10的经历,让我深刻体会到Linux系统权限管理的精妙与严格。当安装进度条莫名其妙卡在60%不动,或是明明安装成功却找不到桌面图标时&…...

如何快速解决ComfyUI ControlNet Aux中DWPose ONNX运行时错误:终极指南

如何快速解决ComfyUI ControlNet Aux中DWPose ONNX运行时错误:终极指南 【免费下载链接】comfyui_controlnet_aux ComfyUIs ControlNet Auxiliary Preprocessors 项目地址: https://gitcode.com/gh_mirrors/co/comfyui_controlnet_aux 你是否在使用ComfyUI C…...

DeepResearchEval框架:标准化研究流程的动态编排引擎

1. 项目背景与核心价值 去年在做一个跨领域研究项目时,我深刻体会到人工构建研究任务流程的痛点:从数据收集、清洗到模型训练和评估,每个环节都需要重复造轮子。不同研究团队对相同问题的评估标准往往不一致,导致结果难以横向比较…...

D3KeyHelper:暗黑3鼠标宏工具终极指南,轻松告别手酸烦恼

D3KeyHelper:暗黑3鼠标宏工具终极指南,轻松告别手酸烦恼 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 厌倦了在暗黑破坏神3…...

终极指南:如何使用KMS智能激活工具永久激活Windows和Office

终极指南:如何使用KMS智能激活工具永久激活Windows和Office 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 你是否曾因Windows系统频繁弹出激活提示而困扰?Office突然变成…...

如何用STDF-Viewer实现半导体测试数据的终极可视化分析

如何用STDF-Viewer实现半导体测试数据的终极可视化分析 【免费下载链接】STDF-Viewer A free GUI tool to visualize STDF (semiconductor Standard Test Data Format) data files. 项目地址: https://gitcode.com/gh_mirrors/st/STDF-Viewer 在半导体制造和测试领域&am…...

输入革命:Hitboxer如何重新定义竞技游戏键盘映射的范式

输入革命:Hitboxer如何重新定义竞技游戏键盘映射的范式 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd 在追求极致操作精度的竞技游戏领域,键盘输入冲突长期困扰着职业玩家与电竞爱好者。…...

深度学习优化器如何影响Transformer的FFN层谱特性

1. 深度学习优化器与FFN层谱特性的内在关联在Transformer架构的训练过程中,优化器的选择往往被视为一个超参数调整问题。然而,最新研究发现,优化器不仅影响收敛速度,更会从根本上改变神经网络内部表示的几何特性。这种改变在Feed-…...

SOCD Cleaner完整指南:告别键盘冲突,4种模式解锁游戏操作新境界

SOCD Cleaner完整指南:告别键盘冲突,4种模式解锁游戏操作新境界 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd 还在为键盘操作时的方向冲突而烦恼吗?SOCD Cleaner&#xff0…...

Java经典面试题汇总:Java Web

1. JSP 和 servlet 有什么区别?JSP 是 servlet 技术的扩展,本质上就是 servlet 的简易方式。servlet 和 JSP 最主要的不同点在于, servlet 的应用逻辑是在 Java 文件中,并且完全从表示层中的 html 里分离开来,而 JSP 的…...

LaTeX长表格排版救星:除了longtable,supertabular和xtab怎么选?附双栏模式下的实战配置

LaTeX长表格排版终极指南:双栏模式下的跨页解决方案 在学术写作中,数据呈现的清晰度直接影响研究成果的传达效果。当遇到需要跨页的长表格时,尤其是在双栏排版的期刊论文或会议报告中,传统表格环境往往力不从心——表格被拦腰截断…...

3大创新特性重塑全面战争MOD开发体验:RPFM架构解析与实践指南

3大创新特性重塑全面战争MOD开发体验:RPFM架构解析与实践指南 【免费下载链接】rpfm Rusted PackFile Manager (RPFM) is a... reimplementation in Rust and Qt6 of PackFile Manager (PFM), one of the best modding tools for Total War Games. 项目地址: http…...