当前位置:首页 > C# > 正文

深入理解 TaskCompletionSource(C# 中手动完成异步任务的利器)

在 C# 的异步编程世界中,TaskCompletionSource<T> 是一个非常强大但常被初学者忽略的工具。它允许你手动控制一个 Task<T> 的完成状态——无论是成功、失败还是取消。本文将用通俗易懂的方式带你掌握 TaskCompletionSource<T> 的核心用法,让你轻松应对各种需要“手动完成任务”的场景。

深入理解 TaskCompletionSource<T>(C# 中手动完成异步任务的利器) TaskCompletionSource C# 异步编程 手动完成任务 第1张

什么是 TaskCompletionSource<T>?

TaskCompletionSource<T> 是 .NET 提供的一个类,用于创建一个可以由开发者手动设置结果Task<T> 对象。换句话说,它不依赖于 async/await 或线程池自动完成,而是由你决定何时、如何完成这个任务。

这在以下场景特别有用:

  • 将事件驱动的 API 转换为基于 Task 的异步方法
  • 实现自定义的异步操作(如超时、重试逻辑)
  • 桥接同步与异步代码
  • 模拟异步行为用于单元测试

基本用法示例

下面是一个最简单的例子:手动设置任务成功完成并返回一个值。

using System;using System.Threading.Tasks;class Program{    static async Task Main(string[] args)    {        // 创建 TaskCompletionSource        var tcs = new TaskCompletionSource<string>();        // 获取关联的 Task        Task<string> task = tcs.Task;        // 模拟在某个时刻手动完成任务        Console.WriteLine("正在等待任务完成...");        await Task.Delay(1000); // 模拟延迟        // 手动设置结果        tcs.SetResult("任务已完成!");        // 等待并获取结果        string result = await task;        Console.WriteLine(result); // 输出:任务已完成!    }}

处理异常和取消

除了成功完成,你还可以手动设置任务为异常或取消状态:

// 设置异常try{    tcs.SetException(new InvalidOperationException("发生错误!"));}catch (Exception ex){    Console.WriteLine(ex.Message);}// 设置取消(需配合 CancellationToken)var cts = new CancellationTokenSource();cts.Cancel();tcs.SetCanceled(); // 注意:SetCanceled() 不带参数,但通常应配合 CancellationToken 使用

实战案例:将事件转换为 Task

假设你有一个基于事件的下载器,你想把它包装成一个 async 方法。这时 TaskCompletionSource<T> 就派上用场了:

public class Downloader{    public event Action<string> OnDownloadCompleted;    public event Action<Exception> OnDownloadFailed;    public void StartDownload(string url)    {        // 模拟异步下载        Task.Run(() =>        {            try            {                // 模拟耗时操作                Thread.Sleep(2000);                OnDownloadCompleted?.Invoke($"{url} 下载成功");            }            catch (Exception ex)            {                OnDownloadFailed?.Invoke(ex);            }        });    }}// 使用 TaskCompletionSource 包装public static Task<string> DownloadAsync(string url){    var tcs = new TaskCompletionSource<string>();    var downloader = new Downloader();    downloader.OnDownloadCompleted += result => tcs.SetResult(result);    downloader.OnDownloadFailed += ex => tcs.SetException(ex);    downloader.StartDownload(url);    return tcs.Task;}// 调用static async Task Main(){    string result = await DownloadAsync("https://example.com/file.txt");    Console.WriteLine(result);}

SEO 关键词回顾

在本文中,我们深入探讨了 C# 中的 TaskCompletionSource,它是实现手动完成任务的核心机制,广泛应用于异步编程场景。无论你是初学者还是有经验的开发者,掌握这一工具都能显著提升你的 C# 编程能力。

记住这四个关键概念:

  • TaskCompletionSource:创建可手动控制的 Task
  • C#:本文使用的编程语言
  • 异步编程:TaskCompletionSource 的主要应用场景
  • 手动完成任务:TaskCompletionSource 的核心功能

小结

TaskCompletionSource<T> 是 C# 异步编程中一个灵活而强大的工具。通过它,你可以将任何非 Task 驱动的操作(如事件、回调、外部系统通知)无缝集成到现代 async/await 流程中。希望这篇教程能帮助你轻松上手,并在实际项目中灵活运用!