Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I return ValueTask if I still use TaskCompletionSource to implement asynchrony?

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?

like image 375
avo Avatar asked Dec 13 '22 08:12

avo


1 Answers

There are pros and cons of each. In the "pro" column:

  1. When returning a result synchronously (i.e. 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
  2. When you are issuing multiple sequential awaitables, you can use a single "value task source" with sequential tokens to reduce allocations

(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.

like image 165
Marc Gravell Avatar answered Jan 12 '23 01:01

Marc Gravell