C# 我是否应该始终完成TaskCompletionSource?

C# 我是否应该始终完成TaskCompletionSource?,c#,task-parallel-library,async-await,taskcompletionsource,C#,Task Parallel Library,Async Await,Taskcompletionsource,如果TaskCompletionSource从未完成(即SetCancelled,SetException或SetResult从未调用),那么TaskCompletionSource及其Task会发生什么?任务会因为从未完成而永远存在吗 在下面的示例中,我有一个参数化测试的简化版本。如果超时(myevent未在1000毫秒内调用),则TaskCompletionSource(tcs)永远不会完成。我有很多这样的测试。我是否需要进行任何类型的清理(例如,确保调用了tcs.SetCancelled(

如果
TaskCompletionSource
从未完成(即
SetCancelled
SetException
SetResult
从未调用),那么
TaskCompletionSource
及其
Task
会发生什么?任务会因为从未完成而永远存在吗

在下面的示例中,我有一个参数化测试的简化版本。如果超时(
myevent
未在1000毫秒内调用),则
TaskCompletionSource
tcs
)永远不会完成。我有很多这样的测试。我是否需要进行任何类型的清理(例如,确保调用了tcs.SetCancelled())

[理论]
[在线数据(“aa”)]
[在线数据(2)]
[在线数据(真实)]
[在线数据(空)]
公共异步任务RaiseMyEvent\u RaiseMyEvent\u带原始值(对象值)
{
var sut=新事物();
var tcs=new TaskCompletionSource();
sut.MyEvent+=(\ux,args)=>tcs.SetResult(args.Value);
sut.RaiseMyEvent(值);
BeSameAs(wait Task.wheny(Task.Delay(1000),tcs.Task),“MyEvent应在1000毫秒内引发”);
tcs.Task.Result.Should().Be(值);
}
在我们进行测试时,我是否有办法改进上述测试(例如,使其更加简洁/简单/可读)

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

使用
TaskCompletionSource
不需要任何清理。事实上,它甚至不允许任何清理。因此,您的问题的答案是“否”

TaskCompletionSource
只是一个概念上简单的数据结构,允许您最多推入一件事情(类型为
T
、异常或取消的结果)。它的
Task
属性公开了一个
Task
,它只是这个承诺的单个东西的包装器,将来某个时候会推送到
TaskCompletionSource
中。它不使用任何任务池

从不将任何内容推入
TaskCompletionSource
是完全有效的。这只对应于将永远“运行”且永远不会完成的
Task

[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);
}