来自取消令牌的任务

本文关键字:任务 令牌 取消 | 更新日期: 2023-09-27 18:30:33

给定一个取消令牌,我想从中创建一个名为等待的任务,该任务永远不会完成,但可以取消。我需要这样的模式,IMO 应该很常见:

async Task DoStuff(Task t, CancellationToken ct)
{
   // t was made from TaskCompletionSource, 
   // both t and ct are beyond my control
   Task t2 = TaskFromCancellationToken(ct);
   await Task.WhenAny(t, t2);
   // do stuff
}

到目前为止,我得到的最好的主意是:

Task TaskFromCancelationToken(CancellationToken ct)
{
    return Task.Delay(Timeout.Infinite, ct);
}

有没有更好的方法来实现这个逻辑?

来自取消令牌的任务

它不是常见,但它很常见,可以成为我的 AsyncEx 库的一部分。我使用这样的东西:

public static Task AsTask(this CancellationToken cancellationToken)
{
    var tcs = new TaskCompletionSource<object>();
    cancellationToken.Register(() => tcs.TrySetCanceled(),
        useSynchronizationContext: false);
    return tcs.Task;
}

更新:这些天,我建议使用类似 CancellationTokenTaskSource ,它可以正确处理所有生命周期,而不会发生资源泄漏。

Task.Delay(Timeout.Infinite, cancellationToken)

您在问题中建议的答案是我知识的最佳解决方案。原因如下:

  • 它是安全的
  • 需要非常小的代码段
  • 标准库

据我所知,Task.Delay方法被很多人大量使用,并且在Microsoft博客上也推荐使用。MSDN 示例。

为什么要自己编写代码(包括测试),利用TaskCompletionSource将取消令牌转换为任务?最好利用标准库而不是重新发明轮子;它们比你的代码更有可能没有错误。