C
C#13mo ago
OptoCloud

❔ Can I Fire and forget ALOT of tasks? If so how do i do this efficiently?

I have a websocket connection, the server will always only have one task that reads from it, but after it has read the message and passed it onto the message handler i want it to begin reading the next message and forget the task it just started... This might result in alot of tasks being started, how do i do this in a efficient manner, or should i not do this at all?
9 Replies
OptoCloud
OptoCloud13mo ago
Example class
public sealed class WebSocketInstance
{
private readonly WebSocket _webSocket;
private readonly ILogger<WebSocketInstance> _logger;

private async Task RunWebSocketAsync(CancellationToken cancellationToken)
{
while (_webSocket.State == WebSocketState.Open)
{
byte[] bytes = ArrayPool<byte>.Shared.Rent(4096);
try
{
WebSocketReceiveResult msg = await _webSocket.ReceiveAsync(bytes, cancellationToken);

// parse message into a body variable

await HandleMessageAsync(body.Value, cancellationToken); // I want to avoid await here
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}
await CloseAsync();
}

private async Task<bool> HandleMessageAsync(ClientMessageBody message, CancellationToken cs)
{
// message handler logic that might call SendAsync and will probably access the this context
}

public async Task SendAsync(ServerMessageBody data, CancellationToken cs)
{
if (_webSocket.State != WebSocketState.Open) return;

// Send logic here
}
}
public sealed class WebSocketInstance
{
private readonly WebSocket _webSocket;
private readonly ILogger<WebSocketInstance> _logger;

private async Task RunWebSocketAsync(CancellationToken cancellationToken)
{
while (_webSocket.State == WebSocketState.Open)
{
byte[] bytes = ArrayPool<byte>.Shared.Rent(4096);
try
{
WebSocketReceiveResult msg = await _webSocket.ReceiveAsync(bytes, cancellationToken);

// parse message into a body variable

await HandleMessageAsync(body.Value, cancellationToken); // I want to avoid await here
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}
await CloseAsync();
}

private async Task<bool> HandleMessageAsync(ClientMessageBody message, CancellationToken cs)
{
// message handler logic that might call SendAsync and will probably access the this context
}

public async Task SendAsync(ServerMessageBody data, CancellationToken cs)
{
if (_webSocket.State != WebSocketState.Open) return;

// Send logic here
}
}
Tinefol
Tinefol13mo ago
Just fire the task and discard result? _ = Task.Run(() => HandleMessageAsync(body.Value, cancellationToken));
OptoCloud
OptoCloud13mo ago
well yeah thats the easy way but i dont think thats smart memory usage n stuff
CrumpetMan
CrumpetMan13mo ago
Why do you think so? CLR has garbage collection
OptoCloud
OptoCloud13mo ago
im aware but this means allocating thousands of tasks that way the same way you would use ArrayPool<> instead of allocating arrays all the time, im asking this question because doing this at such a frequency might be bad
CrumpetMan
CrumpetMan13mo ago
If you're worried about memory, then .NET will realloc as needed (when tasks finish executing). If you're worried about processing power, the thread pool thread takes care of that. It enqueues busy tasks as needed. That means when you're creating thousands of tasks in a short timespan, not all of them will be actively working
sibber
sibber13mo ago
garbage collection isnt free (this also doesnt mean you should also micro optimize everything) anyway
_ = HandleMessageAsync(body.Value, cancellationToken);
_ = HandleMessageAsync(body.Value, cancellationToken);
will fire and forget but keep in mind your method will run sync-ly until the first await
cap5lut
cap5lut13mo ago
in addition to what Cyberres said, there is also ValueTask/ValueTask<T> which are structs so u dont add additional work for the GC which can come in quite handy for fire and forget. ofc dont blindly use it but check out if it fits ur use cases https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1?view=net-7.0 https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/
Accord
Accord13mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts