.NET中TaskCompletionSource的用法小结

 更新时间:2025年12月28日 10:17:39   作者:无风听海  
TaskCompletionSource是一个非常强大的工具,允许开发者以更加灵活的方式控制和管理异步任务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

TaskCompletionSource<T> 是 .NET 中用于控制和管理异步任务 (Task) 的类,广泛用于在异步编程中手动控制任务的完成。它通常与 asyncawait 配合使用,但它本身是用来创建、设置或操作任务的结果的。

TaskCompletionSource<T>的基本概念

在标准的异步编程中,你会看到异步方法返回一个 TaskTask<T> 对象,它代表着一个尚未完成的操作。而 TaskCompletionSource<T> 类允许你手动设置这些任务的状态,例如让任务完成、失败或取消。

TaskCompletionSource<T>类的构造与使用

  1. 构造函数

    • TaskCompletionSource():创建一个新的 TaskCompletionSource<T> 实例。
    • TaskCompletionSource(CancellationToken cancellationToken):带有取消标记的构造函数。

    TaskCompletionSource<T> 本身并不直接执行任务,它仅提供了一些方法来控制任务的状态。

  2. 关键属性

    • Task:TaskCompletionSource<T> 类有一个公开的属性 Task,它返回一个 Task<T> 实例,表示这个任务的状态。你可以通过这个属性来跟踪任务的状态,并通过 await 来等待其完成。
    • Task.IsCompleted:判断任务是否完成。
    • Task.IsFaulted:判断任务是否因错误而失败。
    • Task.IsCanceled:判断任务是否被取消。
  3. 关键方法

    • SetResult(T result):完成任务并提供结果。如果任务已完成(无论是成功、失败还是取消),这会引发异常。
    • SetException(IEnumerable<Exception> exceptions):让任务以失败的状态完成,并报告异常。
    • SetException(Exception exception):让任务以失败的状态完成,并报告单个异常。
    • SetCanceled():将任务标记为已取消状态。
    • TrySetResult(T result):类似于 SetResult,但它不会抛出异常,如果任务已经完成(无论是成功、失败还是取消),会返回 false。
    • TrySetException(IEnumerable<Exception> exceptions):与 SetException 类似,但如果任务已经完成,则返回 false。
    • TrySetException(Exception exception):类似于 SetException,但如果任务已完成,则返回 false。
    • TrySetCanceled():与 SetCanceled 类似,但如果任务已经完成,则返回 false。
  4. 常用场景
    TaskCompletionSource<T> 主要用于那些你无法直接控制任务完成的场景,或者在一些复杂的异步控制流中。以下是一些常见的使用场景:

    • 异步回调转换:如果你有一个基于回调的异步API,但你想使用 Task 来控制它的执行,可以使用 TaskCompletionSource<T>。例如,假设你在处理一个异步的文件读写操作,并且你想将其转换为 Task:

      public Task<string> ReadFileAsync(string path)
      {
          var tcs = new TaskCompletionSource<string>();
      
          // 模拟异步操作的回调
          File.ReadAllTextAsync(path).ContinueWith(task =>
          {
              if (task.IsFaulted)
              {
                  tcs.SetException(task.Exception);  // 设置异常
              }
              else if (task.IsCanceled)
              {
                  tcs.SetCanceled();  // 设置取消
              }
              else
              {
                  tcs.SetResult(task.Result);  // 设置结果
              }
          });
      
          return tcs.Task;
      }
      
    • 手动控制异步任务的完成:有时在异步操作中,任务的完成是由某个外部事件触发的。你可以使用 TaskCompletionSource<T> 来手动完成任务。例如,基于某个标志位或者外部事件来触发任务的完成:

      public Task WaitForExternalEventAsync()
      {
          var tcs = new TaskCompletionSource<object>();
      
          // 假设有一个外部事件
          ExternalEventTriggered += (sender, e) =>
          {
              tcs.SetResult(null);  // 当事件触发时,设置任务完成
          };
      
          return tcs.Task;
      }
      
    • 取消支持的异步操作:你可以将 TaskCompletionSource<T>CancellationToken 配合使用,在任务中支持取消。例如:

      public Task<string> LongRunningTask(CancellationToken cancellationToken)
      {
          var tcs = new TaskCompletionSource<string>();
      
          cancellationToken.Register(() => tcs.SetCanceled());  // 任务取消时标记为已取消
      
          Task.Run(() =>
          {
              try
              {
                  // 模拟长时间运行的操作
                  Thread.Sleep(5000);
      
                  if (!cancellationToken.IsCancellationRequested)
                  {
                      tcs.SetResult("Task Completed");
                  }
              }
              catch (Exception ex)
              {
                  tcs.SetException(ex);
              }
          });
      
          return tcs.Task;
      }
      

例子:使用TaskCompletionSource完成一个异步任务

public Task<string> GetDataAsync()
{
    var tcs = new TaskCompletionSource<string>();

    // 模拟异步操作
    Task.Run(() =>
    {
        try
        {
            // 假设在这里获取数据
            string data = "Hello, world!";
            tcs.SetResult(data);  // 操作成功,设置结果
        }
        catch (Exception ex)
        {
            tcs.SetException(ex);  // 操作失败,设置异常
        }
    });

    return tcs.Task;
}

线程安全

TaskCompletionSource<T> 是线程安全的,可以在多个线程中安全地调用其方法,例如 SetResult、SetException 等。不过,你只应该在任务完成后调用一次这些方法,否则会引发 InvalidOperationException。

总结

TaskCompletionSource<T> 是一个非常强大的工具,允许开发者以更加灵活的方式控制和管理异步任务。它让你能够将基于回调的异步编程模型转化为更加直观和易于管理的 Task 模型,同时还提供了手动控制任务状态(完成、失败或取消)的能力。在处理复杂异步控制流时,TaskCompletionSource<T> 是非常有用的。

到此这篇关于.NET中TaskCompletionSource的用法小结的文章就介绍到这了,更多相关.NET TaskCompletionSource内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论