Read from PipeReader with timeout

Viewed 270

Currently I'm using the following utility extension to read from a PipeReader with a specified timeout. The timeout is required to properly implement Keep-Alive within a HTTP server.

internal static async Task<ReadResult?> ReadWithTimeoutAsync(this PipeReader reader, TimeSpan timeout)
{
    ReadResult? result = null;

    var readTask = Task.Run(async () =>
    {
        result = await reader.ReadAsync();
    });

    var success = await Task.WhenAny(readTask, Task.Delay(timeout)) == readTask;

    if (!success || (result == null))
    {
        return null;
    }

    return result;
}

This code is problematic in a couple of ways, as it introduces locking (within Task.Delay), a lot of allocations and a thread to be handled by the CPU.

Is there a more efficient way to use a PipeReader with read timeouts?

1 Answers

We can use a CancellationToken to implement the timeout in a more efficient manner:

using var cancellation = new CancellationTokenSource(timout);

try
{
    Data = (await Reader.ReadAsync(cancellation.Token)).Buffer;
}
catch (OperationCanceledException)
{
    return null;
}
Related