在集线器连接停止/启动场景下,流的生命周期对客户端而言是多少,以及服务器是否显式中止连接(由于 access_token 超时等触发客户端刷新其连接)。
当连接终止时(由于stop
在客户端上被调用或服务器中止连接),error
订阅者的方法将被调用,并显示错误指示流已终止,因为连接已终止。通常,您应该处理该error
方法并将其视为终端事件(即流永远不会产生额外的对象)。在服务器上,Context.ConnectionAborted
如果连接(任何一方)终止,则将触发令牌,并且您可以停止写入流。
如果您已经在使用 RxJS,我强烈建议您构建一个小型包装器,将您从 SignalR 返回的对象转换为适当的 RxJS Observable
。我们返回的对象实际上不是一个Observable
,但它具有所有相同的基本方法(一个采用和方法subscribe
的对象的complete
方法),因此包装它应该是微不足道的。next
error
我尝试在流上调用 dispose,如果集线器已连接,这很好,但如果连接处于断开状态,则会出错。我想知道这是否是一个错误。
是的,这可能是一个错误。如果您在集线器断开连接后进行处置,我们不应该抛出。你可以在https://github.com/aspnet/SignalR上归档吗?要解决它,您可以相当安全地只try...catch
显示错误并抑制它(或者如果您偏执,可以记录它)。
可以只删除流订阅然后根据需要重新创建,还是会以任何方式泄漏?
您应该始终 dispose
订阅。如果你只是delete
它,那么我们无法知道你已经完成了它,我们永远不会告诉服务器停止。如果您致电dispose
(并且已连接),我们会向服务器发送一条消息“取消”流。在 ASP.NET Core 2.1 中,我们不会向您公开此取消,但我们会停止从ChannelReader
. CancellationToken
在 ASP.NET Core 2.2 中,我们允许您在 Hub 方法中接受 a ,并且dispose
客户端上的方法将在 Hub 方法中触发此令牌。我强烈建议您尝试最新的 ASP.NET Core 2.2 预览版并CancellationToken
在您的 Hub 方法中使用 a 来停止流:
public ChannelReader<object> MyStreamingMethod(..., CancellationToken cancellationToken) {
// pass 'cancellationToken' over to whatever process is writing to the channel
// and stop writing when the token is triggered
}
注意:如果你这样做,你不需要监控Context.ConnectionAborted
,传递给你的 Hub 方法的令牌将涵盖所有取消情况。
在相关说明中,您应该始终使用Channel.CreateBounded<T>(size)
来创建您的频道。如果您使用无界通道,则更容易泄漏内存,因为编写器可以无限期地继续写入。如果您使用有界通道,如果通道中有未读取的项目(例如,客户端已断开连接并且我们已停止读取) ,则写入器将被停止(WriteAsync
并且将“阻塞”)。WaitToWriteAsync
size