6

我正在使用 Microsoft.AspNetCore.SignalR 2.1 v1.0.4,并且使用 v1.0.4 的打字稿客户端正在使用 ChannelReader 流。

通道显示特定于单个实体的事件数据,因此当客户端的用户导航到该单个实体的页面呈现数据时,预计客户端将订阅通道。如果用户导航到相同的页面但针对不同的实体,则客户端将进行另一个订阅调用。

现在我的问题是关于如何最好地取消订阅流,一般来说,在集线器连接停止/启动场景下,流的生命周期对客户端来说是什么,以及服务器是否显式中止连接(由于 access_token 超时所以触发客户端刷新他们的连接)?

似乎没有从 api 显示一些连接状态,所以我目前使用 RxJs Subject 来显示我的 UI 组件/服务的一些连接状态,即当集线器连接的启动调用成功时,我显示“真”,当onclose 回调称为 I 表面“假”。这使我可以尝试在先前订阅的流上调用 dispose 以在连接断开/停止期间进行清理,然后在必要时在成功启动调用时再次调用订阅流。

我尝试在流上调用 dispose,如果集线器已连接,这很好,但如果连接处于断开状态,则会出错。我想知道这是否是一个错误。即使集线器断开连接,我也应该能够处理流吗?

可以只做一个delete streamsubscription然后根据需要重新创建,还是会以任何方式泄漏?

4

1 回答 1

4

在集线器连接停止/启动场景下,流的生命周期对客户端而言是多少,以及服务器是否显式中止连接(由于 access_token 超时等触发客户端刷新其连接)。

当连接终止时(由于stop在客户端上被调用或服务器中止连接),error订阅者的方法将被调用,并显示错误指示流已终止,因为连接已终止。通常,您应该处理该error方法并将其视为终端事件(即流永远不会产生额外的对象)。在服务器上,Context.ConnectionAborted如果连接(任何一方)终止,则将触发令牌,并且您可以停止写入流。

如果您已经在使用 RxJS,我强烈建议您构建一个小型包装器,将您从 SignalR 返回的对象转换为适当的 RxJS Observable。我们返回的对象实际上不是一个Observable,但它具有所有相同的基本方法(一个采用和方法subscribe的对象的complete方法),因此包装它应该是微不足道的。nexterror

我尝试在流上调用 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并且将“阻塞”)。WaitToWriteAsyncsize

于 2018-10-24T17:56:53.587 回答