内存泄漏问题:如何配置SignalR集线器连接以及何时创建新连接

时间:2017-09-09 01:16:18

标签: c# memory-leaks signalr signalr-hub

我有两个关于SignalR集线器连接的相关问题,但在我找到它们之前,我只是给出一些关于我正在做什么的背景信息。

上下文

我有一个应用程序使用SignalR从服务器向前端(Javascript)客户端发送通知。但是,还有一个后端(.NET)客户端,它可以为集线器创建代理。后端客户端处理通知并将其发送到集线器,然后集线器将这些通知发送到前端客户端。

更具体地说,我有一个通知处理类,我们称之为NotificationProcessor.cs。每次创建新通知时,都会实例化NotificationProcessor的实例。实例化NotificationProcessor时,将建立与集线器的代理连接。我有一个类HubProxyService.cs,它从中创建HubConnection对象和IHubProxy对象。它的片段如下:

this.HubConnection = new HubConnection(serverUrl);
this.HubProxy = HubConnection.CreateHubProxy(hubName);
Task t = Task.Run(() => this.HubConnection.Start(new LongPollingTransport()));
t.WaitAndUnwrap();

NotificationProcessor然后使用IHubProxy对象来调用集线器中的方法。

我发现每次HubConnection实例化时创建NotificationProcessor对象,并且在完成时不放置HubConnection会导致内存泄漏。

问题

(1)为了避免内存泄漏,我需要以某种方式处理HubConnection。我读到我能做到

Task.Run(() => this.HubConnection.Stop())

这个问题是我不知道在什么时候我可以称之为。由于使用代理调用hub方法是异步的,我可以在调用hub方法后立即调用它吗?或者,如果从集线器向前端客户端发送通知有延迟,这会导致问题吗?

我想另一种选择是将HubConnection初始化包含在using语句中,如此

using (HubConnection connection = new HubConnection(serverUrl))
{

}

我听说这也有问题,因为处理HubConnection可能需要一段时间。

有没有比另一个更好的?后者似乎更惯用,而前者更明确,可能更好。

(2)为每个创建的HubConnection实例创建NotificationProcessor是不是一个好主意?有没有办法坚持这种联系(即,使其静止或类似)?我对对象生命周期和副作用有一个不稳定的理解,特别是因为这个应用程序部署在云上,我不知道一个HubConnection实例被多次使用意味着什么。它是在线程之间共享的吗?节点之间(我使用的是Redis背板)?用户之间?如果在每次需要发送数据时保持实例化是很昂贵的话,保持连接打开是有意义的,但是当我在多个节点上部署在云上时,我只是不明白它是如何工作的。每次建立新连接似乎更容易。

1 个答案:

答案 0 :(得分:3)

这个问题是在不久前发布的,但看不到回应,我以为我会插话。

鉴于您所描述的内容,我个人建议为每个处理器重新使用HubConnection的静态实例,并为每个处理器添加一个新的HubProxy。只需确保处理器处理后IHubProxy可以正确处理。

每个连接都将被视为SignalR Hub的单独客户端,因此如果您需要在同一进程中使用单独的通知或客户端,则需要单独的连接,但在您的情况下,所有这些通知都来自同一个客户。

谨慎之言

请务必查看HubConnection

的主题安全性
  

线程安全

     

任何公共静态(在Visual Basic中共享)成员   这种类型是线程安全的。任何实例成员都不能保证   是线程安全的。