Is there still a benefit in returning ValueTask
if I use TaskCompletionSource
to implement actual asynchrony?
As I understand it, the purpose of ValueTask
is to reduce allocations, but allocations are still there when awaiting TaskCompletionSource.Task
. Here is a simple example to illustrate the question:
async ValueTask DispatcherTimerDelayAsync(TimeSpan delay)
{
var tcs = new TaskCompletionSource<bool>();
var timer = new DispatcherTimer();
timer.Interval = delay;
timer.Tick += (s, e) => tcs.SetResult(true);
timer.Start();
try
{
await tcs.Task;
}
finally
{
timer.Stop();
}
}
Should I rather be returning Task
(versus ValueTask
) from DispatcherTimerDelayAsync
, which itself is always expected to be asynchronous?
There are pros and cons of each. In the "pro" column:
Task<T>
), using ValueTask<T>
avoids an allocation of the task - however, this doesn't apply for "void" (i.e. non-generic Task
), since you can just return Task.CompletedTask
(a special-case of "2" might be amortization via tools like PooledAwait
)
It doesn't feel like either of those apply here, but: if in doubt, remember that it is allocation-free to return a Task
as a ValueTask
(return new ValueTask(task);
), which would allow you to consider changing the implementation to an allocation-free one later without breaking the signature. You still pay for the original Task
etc of course - but exposing them as ValueTask
doesn't add any extra.
In all honesty, I'm not sure I'd worry too much about this in this case, since a delay is ways going to be allocatey.
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