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

C# TaskCompletionSource.SetResult 用法详解

一、基本概念

TaskCompletionSource<T> 允许手动控制一个 Task 的完成状态,SetResult 用于将任务标记为成功完成并设置结果值。

二、基本用法

1. 创建并设置结果

var tcs = new TaskCompletionSource<int>();// 在某个地方设置结果
tcs.SetResult(42);// 获取结果
int result = await tcs.Task;
Console.WriteLine(result); // 输出: 42

2. 在异步操作中使用

var tcs = new TaskCompletionSource<string>();// 模拟异步操作
Task.Run(() =>
{Thread.Sleep(1000);tcs.SetResult("操作完成");
});string result = await tcs.Task;
Console.WriteLine(result); // 输出: 操作完成

三、实际应用场景

1. 包装传统异步模式

// 将 Event-based 异步模式转换为 Task
public Task<string> DownloadStringAsync(string url)
{var tcs = new TaskCompletionSource<string>();var webClient = new WebClient();webClient.DownloadStringCompleted += (s, e) =>{if (e.Error != null)tcs.SetException(e.Error);else if (e.Cancelled)tcs.SetCanceled();elsetcs.SetResult(e.Result);};webClient.DownloadStringAsync(new Uri(url));return tcs.Task;
}

2. 超时控制

public static Task<T> WithTimeout<T>(Task<T> task, TimeSpan timeout)
{var tcs = new TaskCompletionSource<T>();// 设置超时计时器var timer = new Timer(_ => {tcs.TrySetException(new TimeoutException("操作超时"));}, null, timeout, Timeout.InfiniteTimeSpan);task.ContinueWith(t =>{timer.Dispose();if (t.IsFaulted)tcs.TrySetException(t.Exception.InnerExceptions);else if (t.IsCanceled)tcs.TrySetCanceled();elsetcs.TrySetResult(t.Result);});return tcs.Task;
}

3. 多个操作竞争

public static Task<T> FirstOf<T>(params Task<T>[] tasks)
{var tcs = new TaskCompletionSource<T>();foreach (var task in tasks){task.ContinueWith(t =>{if (t.Status == TaskStatus.RanToCompletion)tcs.TrySetResult(t.Result);});}return tcs.Task;
}

四、重要注意事项

1. 避免重复设置

var tcs = new TaskCompletionSource<int>();// ✅ 正确 - 使用 TrySetResult
tcs.TrySetResult(1);
tcs.TrySetResult(2); // 不会抛异常,但结果仍然是 1// ❌ 错误 - 使用 SetResult 会抛异常
tcs.SetResult(1);
tcs.SetResult(2); // 抛出 InvalidOperationException

2. 线程安全考虑

var tcs = new TaskCompletionSource<int>();
object lockObject = new object();
bool isSet = false;void SetResultSafely(int value)
{lock (lockObject){if (!isSet){tcs.SetResult(value);isSet = true;}}
}

3. 结合取消令牌

public Task<int> DoWorkAsync(CancellationToken cancellationToken)
{var tcs = new TaskCompletionSource<int>();// 注册取消回调cancellationToken.Register(() =>{tcs.TrySetCanceled(cancellationToken);});Task.Run(() =>{// 模拟工作for (int i = 0; i < 10; i++){cancellationToken.ThrowIfCancellationRequested();Thread.Sleep(100);}tcs.TrySetResult(42);});return tcs.Task;
}

五、完整示例

class Program
{static async Task Main(){// 示例1: 基本使用var result = await CreateCompletedTask();Console.WriteLine($"结果: {result}");// 示例2: 异步操作包装var data = await FetchDataAsync();Console.WriteLine($"数据: {data}");}static Task<int> CreateCompletedTask(){var tcs = new TaskCompletionSource<int>();tcs.SetResult(100);return tcs.Task;}static Task<string> FetchDataAsync(){var tcs = new TaskCompletionSource<string>();Task.Run(() =>{try{// 模拟网络请求Thread.Sleep(2000);tcs.SetResult("获取的数据");}catch (Exception ex){tcs.SetException(ex);}});return tcs.Task;}
}

六、总结

  • SetResult 用于手动完成任务并设置结果

  • 只能调用一次,后续调用会抛出异常

  • 推荐使用 TrySetResult 来避免异常

  • 适用于包装传统异步模式、实现超时控制等场景

http://www.dtcms.com/a/553795.html

相关文章:

  • 网站建设模板html网站开发工程师岗位职责要求
  • 【Linux network和NetworkManager双网卡主备模式绑定】
  • SSO 单点登录
  • Linux 中如何查看系统的位数
  • 云南建设企业网站修改wordpress首页缩略图尺寸
  • 网站的投票系统怎么做wordpress文章类模板
  • AI智能体如何让用户洞察更简单、更快速、更精准
  • 离线测试与在线测试
  • linux安装kafka
  • 13. React中为什么使用setState
  • 电力电子技术 第十章——可控整流器
  • 高端网站建设seo电子商务网站建设携程
  • 知名网站制作全包19寸 网站做多大
  • MoE (Mixture of Experts)
  • 福建省城乡建设厅网站wordpress演示地址转换短网址
  • 实验:服务端建立nfs服务 客户端挂载该服务
  • 大数据分析与应用实验报告(黑龙江大学)
  • 网站整体结构企业邮箱如何查询
  • GRUB配置文件解析与启动流程详解
  • 静态 IP 深度用户体验手记:Cliproxy 稳定性与便捷性实测
  • 基于Springboot + vue3实现的药材中药资源共享平台
  • 杭州的设计网站建设企业网站建设原则是
  • Configuration Key
  • sns社交网站源码上海有限公司有哪些
  • 基于React的开源框架Next.js、UmiJS、Ant Design Pro
  • KVM在centos上离线安装
  • gateway配置自定义转发
  • 【洛谷】枚举专题-普通枚举 经典题解之铺地毯、回文日期、扫雷
  • GPU机器-显卡占用
  • 网站关键词抓取id wordpress