【问题标题】:Read from PipeReader with timeout从 PipeReader 读取超时
【发布时间】:2020-06-21 07:19:04
【问题描述】:

目前我正在使用以下实用程序扩展来读取具有指定超时的PipeReader。在 HTTP 服务器中正确实现 Keep-Alive 需要超时。

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;
}

这段代码在几个方面存在问题,因为它引入了锁定(在Task.Delay 内)、大量分配和一个由 CPU 处理的线程。

有没有更有效的方法来使用 PipeReader 读取超时?

【问题讨论】:

  • 你不能只使用ReadAsync 传递一个CancellationToken 是超时吗? (即CancelAfter
  • @MarcGravell 哦 - 当然,谢谢。
  • 附带说明:如果您尝试实现一个 http 服务器,请注意 Kestrel 的实现非常好,并且很容易挂钩;仅将其用于繁重的工作可能会更容易
  • 目标实际上是实现 HTTP 服务器本身(并理解 HTTP/2 之类的协议)。我不时查看 Kestrel 的源代码,看看那里是如何实现的。

标签: c# system.io.pipelines


【解决方案1】:

我们可以使用CancellationToken 以更有效的方式实现超时:

using var cancellation = new CancellationTokenSource(timout);

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

【讨论】:

    猜你喜欢
    • 2019-11-22
    • 2021-02-12
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多