Stream 是否有可用的阻塞读取方法?

问题描述 投票:0回答:1

我正在用 C# 编写一个应用程序,以通过 Web 应用程序远程打开 Docker 容器的终端。我需要读取 Docker.NET 客户端返回的流并通过 Web 套接字转发读取的字节。

如果我调用 Stream.Read 并且没有可用数据,它只会返回 0,而不等待数据可用。我花了一段时间寻找阻塞 Read 调用,但没有找到。我知道 .NET 有

Console.Read()
,它会一直等待标准输入中的输入。它是如何实现这种阻塞调用的 - 他们使用循环还是有可用的阻塞方法?

我使用 while 循环编写了下面的代码,并检查是否读取了任何字节。是否需要添加Thread.Sleep或Task.Delay以避免消耗太多CPU?

async Task ForwardStreamViaWebSocket(Stream stream, WebSocket webSocket, CancellationToken cancellationToken)
{
    var buffer = new byte[1024];

    while (!cancellationToken.IsCancellationRequested)
    {
        var bytesRead = 0;

        // Any blocking Read method available instead of looping?
        while (bytesRead == 0)
        {
            bytesRead = stream.Read(buffer, 0, buffer.Length);
            Thread.Sleep(100);  // Is this really required?
        }

        var arraySegment = new ArraySegment<byte>(buffer, 0, bytesRead);
        await webSocket.SendAsync(arraySegment, WebSocketMessageType.Binary, false, cancellationToken);
    }
}
c# .net stream blocking
1个回答
0
投票

Stream.Read 是一个阻塞调用,根据 documentation 它不应该返回,除非它有一些数据,或者到达流的末尾:

仅当请求零字节或流中不再有数据并且预计不再有数据(例如关闭的套接字或文件结尾)时,Read 才会返回 0。即使尚未到达流的末尾,实现也可以自由地返回比请求更少的字节。

所以不需要睡眠。但是,您读取数据的代码是错误的,并且最多只能读取一个缓冲区的数据。请参阅

如何将 Stream 转换为 byte[]
以从流中读取所有数据。

Ofc,对于第三方流,不合格的实现总是可能的。因此,您可能想确认所有数据均已实际读取。

© www.soinside.com 2019 - 2024. All rights reserved.