Since we expect to be reading frequently, and for us to often be reading when data is already available to be consumed, should SendLoopAsync return ValueTask rather than Task, so that we can make it allocation-free?
// Caller
_ = Task.Factory.StartNew(_ => SendLoopAsync(cancellationToken), TaskCreationOptions.LongRunning, cancellationToken);
// Method
private async ValueTask SendLoopAsync(CancellationToken cancellationToken)
{
while (await _outputChannel.Reader.WaitToReadAsync(cancellationToken).ConfigureAwait(false))
{
while (_outputChannel.Reader.TryRead(out var message))
{
using (await _mutex.LockAsync(cancellationToken).ConfigureAwait(false))
{
await _clientWebSocket.SendAsync(message.Data.AsMemory(), message.MessageType, true, cancellationToken).ConfigureAwait(false);
}
}
}
}
No, there is no value at the
SendLoopAsyncreturning aValueTaskinstead ofTask. This method is invoked only once in your code. The impact of avoiding a single allocation of a tiny object is practically zero. You should consider usingValueTasks for asynchronous methods that are invoked repeatedly in loops, especially in hot paths. That's not the case in the example presented in the question.As a side note, invoking asynchronous methods with the
Task.Factory.StartNew+TaskCreationOptions.LongRunningcombination is pointless. The newThreadthat is going to be created, will have a very short life. It's gonna be terminated immediately when the code reaches the firstawaitof an incomplete awaitable inside the async method. Also you are getting back a nestedTask<Task>, which is tricky to handle. UsingTask.Runis preferable. You can read here the reasons why.Also be aware that the
Nito.AsyncEx.AsyncLockclass is not optimized for memory-efficiency. Lots of allocations are happening every time the lock is acquired. If you want a low-allocation synchronization primitive that can be acquired asynchronously, your best bet currently is probably to use aChannel<object>instance, initialized with a singlenullvalue: retrieve the value to enter, store it back to release.