The title says it all:
The specs explicitly say that you must never await a ValueTask more than once - because in particular in the truly asynchronous case, the backing state machine may be pooled and recycled for other ValueTasks after awaiting it.
But what about awaiting less than once - i.e., never? Could this cause any issues? For example, would the backing state still be able to be returned to the pool even if nobody awaited the result?
async Task IsThisLegal()
{
var _ = SomeValueTask();
await Task.Delay(10);
// The value task would have completed by now, but we're not awaiting it. Is that ok?
}
async ValueTask<bool> SomeValueTask()
{
await Task.Delay(TimeSpan.FromSeconds(1));
return true;
}
Do you have to await a
ValueTask
?
No. Not nessesarily.
Never awaiting. Could this cause any issues?
Yes, potentially.
Stream
class, equipped with ReadAsync
and WriteAsync
APIs. By not awaiting the ValueTask
, you can't know when it's safe to proceed with the next operation on the same instance of the component.ValueTask
s are frequently implemented with an IValueTaskSource
backing state that is pooled and reused, minimized the allocations and reducing the pressure on the garbage collector. By not awaiting the ValueTask
, the component has no way to know that the ValueTask
has been consumed, so it can't reuse the backing state. As a result it will create a new backing state for the next operation. There is no formal way to tell the component that "I promise to never await
this ValueTask
". All IValueTaskSource
implementations that I've seen use the GetResult
method as an indicator that the ValueTask
has been consumed. The GetResult
is called automatically by the .NET infrastructure, whenever a ValueTask
is awaited.