来自取消令牌的任务
本文关键字:任务 令牌 取消 | 更新日期: 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
将取消令牌转换为任务?最好利用标准库而不是重新发明轮子;它们比你的代码更有可能没有错误。