【发布时间】:2017-09-09 01:16:18
【问题描述】:
我有两个关于 SignalR 集线器连接的相关问题,但在我回答它们之前,我将提供一些关于我正在做什么的背景信息。
上下文
我有一个使用 SignalR 将通知从服务器发送到前端 (Javascript) 客户端的应用程序。但是,还有一个后端 (.NET) 客户端可以创建到集线器的代理。后端客户端处理通知并将它们发送到集线器,然后集线器将这些通知发送到前端客户端。
更具体地说,我有一个通知处理类,我们称之为NotificationProcessor.cs。每次创建新通知时,都会实例化一个 NotificationProcessor 的实例。当NotificationProcessor 被实例化时,到集线器的代理连接就建立起来了。我有一个类HubProxyService.cs,它从中创建HubConnection 对象和IHubProxy 对象。它的一个sn-p如下:
this.HubConnection = new HubConnection(serverUrl);
this.HubProxy = HubConnection.CreateHubProxy(hubName);
Task t = Task.Run(() => this.HubConnection.Start(new LongPollingTransport()));
t.WaitAndUnwrap();
NotificationProcessor 然后使用IHubProxy 对象调用集线器中的方法。
我发现每次实例化NotificationProcessor 时创建HubConnection 对象,并且在完成后不释放HubConnection 会导致内存泄漏。
问题
(1) 为了避免内存泄漏,我需要以某种方式处理HubConnection。我读到我能做到
Task.Run(() => this.HubConnection.Stop())
这个问题是我不知道什么时候可以调用它。由于使用代理调用 hub 方法是异步的,我可以在调用 hub 方法后立即调用它吗?或者,如果将通知从集线器发送到前端客户端出现延迟,这会导致问题吗?
我想另一种选择是将 HubConnection 初始化包装在 using 语句中,就像这样
using (HubConnection connection = new HubConnection(serverUrl))
{
}
我听说这也可能有问题,因为处理 HubConnection 可能需要一段时间。
有没有比另一个更好的?后者似乎更惯用,而前者更明确,可能效果更好。
(2) 为创建的每个NotificationProcessor 实例创建HubConnection 是不是一个坏主意?有没有办法保持这种连接(即,使其成为静态或类似的东西)?我对对象生命周期和副作用的理解并不牢固,特别是因为这个应用程序部署在云上,我不知道一个HubConnection 实例被多次使用意味着什么。它在线程之间共享吗?节点之间(我使用的是 Redis 背板)?用户之间?如果每次需要发送数据时保持实例化它的成本很高,那么保持连接打开是有意义的,但我只是不明白当它跨多个节点部署在云上时它是如何工作的。每次都建立新的连接似乎更容易。
【问题讨论】:
标签: c# memory-leaks signalr signalr-hub