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

问题描述

我正在使用带有 .NET 客户端的 System.Threading.Channel 进行 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
    }
}

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

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

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

解决方法

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

这里是一个快速总结:

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

还有:

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...