CA2012 warning when using ValueTask with discard

212 Views Asked by At

I am making a simple TCP server and stumbled on this article by Marc Gravell mentioning the following:

Use ValueTask[], unless you absolutely can't because the existing API is Task[], and even then: at least consider an API break

So I changed my HandleClient() method to return ValueTask rather than Task:

public async Task Start()
{
    TcpListener.Start();
    Console.WriteLine($"Server started. Listening on {ServerIP}:{ServerPort}");

    while (true)
    {
        try
        {
            TcpClient client = await TcpListener.AcceptTcpClientAsync();
            _ = HandleClient(client);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error accepting client: {ex.Message}");
        }
    }
}

private async ValueTask HandleClient(TcpClient client) 
{
    ...
    int bytes = await stream.ReadAsync(buffer, cts.Token);
    ...
    await stream.WriteAsync(response);
    ...
}

After changing the return type to ValueTask though, I am getting the following warning: CA2012: ValueTask instances returned from method calls should always be used, typically awaited. Not doing so often represents a functional bug, but even if it doesn't, it can result in degraded performance if the target method pools objects for use with ValueTasks.

However, I cannot use await here because the while loop has to keep running to accept connections concurrently while HandleClient() executes on a different thread. From this github issue, it is suggested to use HandleClient().Preserve(), but doesn't that defeat the purpose of changing my method to ValueTask since according to MSDN documentation:

You can use the Preserve() method to convert this ValueTask into the instance backed by a regular Task that is safe to await multiple times.

So, if I use Preserve() then I am basically using a regular Task from what I understand, and I might as well just change HandleClient() back to return Task instead.

I also tried assigning it to a variable and doing so does get rid of the warning, but I don't know if that solves the problem (if it even exists).

var t = HandleClient(client);

This assignment also does not give me the regular warning CS0129: The variable is assigned but its value is never used, so maybe that is actually the solution?

0

There are 0 best solutions below