将 Channels 与 SignalR 服务器到客户端流式传输一起使用时,是否保证将服务器端 Complete 传送到客户端?

When using Channels with SignalR server-to-client streaming, is the server-side Complete guaranteed to be delivered to the client?

我正在使用 System.Threading.Channel 和 .NET 客户端进行 SignalR 服务器到客户端的流式传输。用法是相当基础的,类似于介绍 docs.

中描述的内容

集线器代码类似这样:

public ChannelReader<byte[]> Retrieve(Guid id, CancellationToken cancellationToken)
{
    var channel = Channel.CreateBounded<byte[]>(_limit);
    _ = WriteItemsAsync(channel.Writer, id, cancellationToken);
    return channel.Reader;
}

private async Task WriteItemsAsync(ChannelWriter<byte[]> writer, Guid id, CancellationToken cancellationToken)
{
    Exception localException = null;
    try
    {
        //loop and write to the ChannelWriter until finished
    }
    catch (Exception ex)
    {
        localException = ex;
    }
    finally
    {
        writer.Complete(localException);
    }
}

客户端与此类似:

var channel = await hubConnection.StreamAsChannelAsync<byte[]>("Retrieve", _guid, cancellationTokenSource.Token);

while (await channel.WaitToReadAsync())
{
    while (channel.TryRead(out var data))
    {
        //handle data
    }
}

当我的集线器方法完成流式传输时,它会在其 ChannelWriter 上调用 Complete()。据推测,SignalR 在内部看到对相应 ChannelReaderComplete 调用,将其转换为内部 SignalR 消息并将其传递给客户端。然后,客户端自己的 ChannelReader 被 SignalR 标记为完成,我的客户端代码在流上完成自己的工作。

从服务器到客户端的“完成”通知是否保证被传送?在集线器向客户端广播非流式消息的其他情况下,它通常“触发并忘记”,但我必须假设在流媒体 Channel 上调用 Complete 已确认交付,否则客户端可能处于持有流媒体 ChannelReader 的状态在服务器认为流已关闭时无限期打开。

这个问题不太重要,但我问的原因是我试图缩小这样一种情况,即使用 SignalR 流接口的数据流管道偶尔会挂起,这似乎是唯一的一点它挂在 SignalR 客户端的某个地方。

我在 github 上询问了开发人员:https://github.com/dotnet/aspnetcore/issues/30128

这里是一个简短的总结:

“SignalR 上的消息与 TCP 一样可靠。基本上这意味着要么您收到消息,要么连接关闭。在这两种情况下,客户端的通道都将完成。”

并且:

“是的,它不应该永远挂起。它要么发送完整的消息,要么断开连接。无论哪种方式,挂起都是客户端中的错误”