What happens to a TaskCompletionSource
and its Task
if the TaskCompletionSource
is never completed (i.e. SetCancelled
, SetException
or SetResult
is never called? Would the Task
live on forever because it never completes?
In the below example I have a simplified version of a parameterized test. In case of a timeout (MyEevent
is not called within 1000ms) the TaskCompletionSource
(tcs
) is never completed. I have a lot of tests like this. Do I need to do any sort of cleanup (e.g. make sure tcs.SetCancelled() is called).?
[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);
}
While we are at it, is there any way I could improve the above test (e.g. make it even more concise/simple/readable)?
Using a
TaskCompletionSource<T>
doesn't require any cleanup. In fact, it doesn't even admit any cleanup. So the answer to your question is "no."The
TaskCompletionSource<T>
is just a conceptually simple data structure that allows you to push in at most a single thing (a result of typeT
, an exception, or a cancellation). ItsTask
property exposes aTask<T>
that is just a wrapper around this promised single thing that will be pushed into theTaskCompletionSource<T>
at some time in the future. It does not use the task pool whatsoever.To never push anything into a
TaskCompletionSource<T>
is perfectly valid. This just corresponds to aTask<T>
that will "run" forever and never complete.