我是否应该总是完成一个任务完成源

本文关键字:一个 任务 是否 | 更新日期: 2023-09-27 18:32:46

如果TaskCompletionSource从未完成,TaskCompletionSource及其Task会发生什么情况(即 SetCancelledSetExceptionSetResult从未被召唤?Task会因为它永远不会完成而永远存在吗?

在下面的示例中,我有一个参数化测试的简化版本。在超时的情况下(MyEevent在1000ms内没有被调用),TaskCompletionSourcetcs)永远不会完成。我有很多这样的测试。我是否需要进行任何类型的清理(例如,确保 tcs。SetCancel() 被调用)。?

[Theory]
[InlineData("aa")]
[InlineData(2)]
[InlineData(true)]
[InlineData(null)]
public async Task RaiseMyEvent_RaisesMyEvent_WithOriginalValue(object value)
{
    var sut = new Thing();
    var tcs = new TaskCompletionSource<object>();
    sut.MyEvent += (_, args) => tcs.SetResult(args.Value);
    sut.RaiseMyEvent(value);
    tcs.Task.Should().BeSameAs(await Task.WhenAny(Task.Delay(1000), tcs.Task), "MyEvent should be raised within 1000ms");
    tcs.Task.Result.Should().Be(value);
}

当我们使用它时,有什么方法可以改进上述测试(例如,使其更加简洁/简单/可读)?

我是否应该总是完成一个任务完成源

我是否需要进行任何类型的清理(例如,确保调用tcs.SetCancelled())?

使用TaskCompletionSource<T>不需要任何清理。事实上,它甚至不承认任何清理。所以你的问题的答案是"不"。

TaskCompletionSource<T>只是一个概念上简单的数据结构,它最多允许您推送单个内容(类型 T异常或取消的结果)。它的Task属性公开了一个Task<T>,它只是这个承诺的单一事物的包装器,该事物将在将来的某个时间被推入TaskCompletionSource<T>。 它不使用任何任务池。

永远不要把任何东西推到TaskCompletionSource<T>是完全有效的。 这只是对应于一个将永远"运行"且永远不会完成的Task<T>