新闻中心

C# TaskCompletionSource的用法 - 将回调模式转换为async/await

2025-12-08
浏览次数:
返回列表
TaskCompletionSource是C#中将回调式异步操作包装为可await的Task的核心工具,不执行异步逻辑,仅手动控制Task完成状态(成功/失败/取消),适用于桥接事件、回调、IAsyncResult等非Task异步模型。

c# taskcompletionsource<t>的用法 - 将回调模式转换为async/await -

TaskCompletionSource 是 C# 中把“回调式异步操作”包装成 Task<t></t>、从而支持 await 的核心工具。它不执行任何异步逻辑,只负责手动控制一个 Task 的完成状态(成功、失败、取消)。

什么时候需要 TaskCompletionSource

常见于以下场景:

  • 调用老式 API(比如基于事件或回调的 SDK,如 WebSocket.OnMessage、HttpClient.SendAsync 的旧封装)
  • 需要自己定义异步契约,比如实现超时控制、延迟触发、信号等待(类似 ManualResetEventSlim + Task)
  • 桥接非 Task 的异步模型(如 Begin/End 模式、IAsyncResult)

基本用法:三步走

以“监听一次 WebSocket 消息”为例:

var tcs = new TaskCompletionSource<string>();// 1. 订阅回调(比如 WebSocket 收到消息时触发)
webSocket.OnMessage += (msg) =>
{
// 2. 成功完成 Task,值为 msg
tcs.TrySetResult(msg);
};// 3. 返回可 await 的 Task
return tcs.Task;

调用方就可以这样写:

string msg = await WaitForNextMessage(); // 干净、线性、可异常传播

务必注意 TrySetXXX 的安全性

TrySetResult/TrySetException/TrySetCanceled 是线程安全且幂等的 —— 多次调用只生效第一次,不会抛异常。推荐始终用 TrySet* 系列,而不是 Set*

AdMaker AI AdMaker AI

从0到爆款高转化AI广告生成器

AdMaker AI 65 查看详情 AdMaker AI

常见错误:

  • 重复调用 SetResult → 抛 InvalidOperationException
  • 在 Task 已完成后再设置 → 同样崩溃
  • 忘记处理异常或取消路径 → Task 永远不完成(死等)

配合 CancellationToken 实现可取消等待

不能直接取消 TaskCompletionSource 本身,但可以监听 token 并主动取消:

var tcs = new TaskCompletionSource<string>();using var registration = cancellationToken.Register(() =>
{
tcs.TrySetCanceled(); // 注意:传入 token 可选,但建议显式传入
});// ... 后续回调中调用 TrySetResult 或 TrySetException

这样 await tcs.Task 就能响应 cancellationToken,抛出 OperationCanceledException

基本上就这些。它不复杂,但容易忽略线程安全和完成唯一性 —— 用好 TrySet* 和及时清理资源(比如注销事件),就能稳稳把回调转成 async/await。

以上就是C# TaskCompletionSource的用法 - 将回调模式转换为async/await的详细内容,更多请关注其它相关文章!


# 适用于  # 动态网站建设试题卷  # 建设平台网站推荐模板  # 平板能不能做网站推广  # 西安360网站推广  # 关键词排名软件询问l火18星  # 南京seo排名哪家专业  # 自制推广网站有哪些类型  # 奥运村网站推广  # 赞伯营销推广  # 沧州老网站优化排名推广  # 相关文章  # websocket  # 什么时候  # 桥接  # 如何实现  # 它不  # 中文网  # 就能  # 转换为  # 回调  # c#  # ai  # 工具 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 夸克浏览器桌面版同步不了书签怎么处理 夸克浏览器跨设备同步异常解决方案  微信网页版扫码登录入口 微信网页版二维码登录入口  Highcharts 雷达图径向轴标签定制指南:利用多Y轴实现数值标注  Win11怎么设置鼠标主按键_Win11鼠标左右键功能互换  Win11如何使用Windows Sandbox Win11沙盒功能开启与使用教程【详解】  AI泡沫首次被“刺破”:GPU十年都无法存活!  为什么简单的XML文件也会解析失败? 检查隐藏的非打印字符(如BOM)的方法  Adobe PDF表单中利用J*aScript解析与格式化日期组件的教程  MAC的“快捷指令”怎么同步到iPhone_MAC利用iCloud同步所有设备的自动化指令  c++中为什么推荐使用using替代typedef_c++现代化类型别名  怎么在html里运行vbs脚本_html中运行vbs脚本方法【教程】  Linux如何排查内存不足OOME问题_LinuxOOM分析教程  HTML长属性值处理:表单action路径优化与代码规范应对  在Go Martini框架中高效服务动态生成图像的实践指南  晋江读书网页版在线登录 晋江读书电脑版官网  QQ邮箱官方登录入口_QQ邮箱网页版快捷使用平台  Golang如何使用context实现超时取消_Golang context超时取消模式实践  CSS实现侧边栏导航项全宽圆角悬停背景效果  Odoo 16:在表单视图中基于当前记录动态修改Tree视图属性  poki免费入口快捷访问 poki人气小游戏直接玩站点  谷歌浏览器无痕模式怎么开 Chrome开启无痕浏览设置方法【教程】  使用Python高效删除Word宏并转换DOCM为DOCX格式  J*aScript中向JSON对象添加新属性的正确姿势  漫蛙2在线漫画入口 漫蛙正版漫画网页版直达  Composer如何在生产环境安全地执行composer update  支付宝解绑银行卡步骤_支付宝如何解除绑定银行卡  Tailwind CSS line-clamp 布局问题解析与修复指南  Django通过AJAX异步上传图片并保存至模型的完整指南  J*aScript对象创建方式_J*aScript设计模式应用  企业名称高精度匹配:N-gram方法在结构相似性分析中的应用  AI抖音网页版免费视频入口 AI抖音网页端最新视频实时观看  如何在J*a中实现统一对象行为接口_项目大型化时的接口规范化  mc.js免安装版 mc.js一键畅玩入口  html怎么运行外部js文件中的函数_运html外js文件函数法【技巧】  Golang切片为何属于引用类型_Golang slice底层结构与引用语义说明  Win11怎么开启卓越性能模式 Win11电源选项启用高性能释放硬件潜力【方法】  Angular中父组件异步更新子组件复选框状态的实践指南  Eclipse怎么运行工程_Eclipse工程运行配置说明  Win11如何开启讲述人功能 Win11屏幕阅读器(讲述人)开启与关闭【教程】  地铁跑酷免费秒玩入口链接 地铁跑酷小游戏免费秒玩网站  邮编格式怎么匹配地址_根据邮编格式快速匹配详细地址的技巧  Steam官网入口直达 Steam注册及登录步骤  Win11 BitLocker密码忘了怎么办 Win11找回BitLocker恢复密钥方法【解决】  聚水潭ERP登录页面入口 聚水潭ERP官网登录界面  PPT平滑切换怎么做 PPT炫酷“平滑”切换动画制作教程【必学】  深入理解J*a编译器的兼容性选项:从-source到--release  必由学官网快捷入口 必由学网页版在线学习平台  在Runstone环境中高效处理TasteDive API的JSON数据  百度浏览器字体显示异常偏小_百度浏览器字体渲染修复方案  漫蛙网页登录入口 漫蛙漫画官方授权网址 

搜索