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)?
Do I need to do any sort of cleanup (e.g. make sure
tcs.SetCancelled()
is called)?
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 type T
, an exception, or a cancellation). Its Task
property exposes a Task<T>
that is just a wrapper around this promised single thing that will be pushed into the TaskCompletionSource<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 a Task<T>
that will "run" forever and never complete.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With