gpt4 book ai didi

c# - 即使处置了集线器连接,也不会从堆中删除 SignalR 对象

转载 作者:太空宇宙 更新时间:2023-11-03 12:23:33 25 4
gpt4 key购买 nike

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

这是创建集线器连接和代理以将消息发送到集线器的后端客户端的片段:

HubConnection hubConnection = new HubConnection(serverUrl);
IHubProxy hubProxy = hubConnection.CreateHubProxy(hubName);
Task t = Task.Run(() => hubConnection.Start(new LongPollingTransport()));
t.WaitAndUnwrap();
if (hubProxy != null && hubConnection.State == ConnectionState.Connected)
{
await hubProxy.Invoke("MessageClients", messageArgs);
}

代码显然还有更多内容,但涵盖了基本部分。

关键部分是,每次创建一条消息时,都会调用这段代码。这意味着为每条需要发送到集线器然后发送到前端客户端的消息创建了一个 HubConnection 对象。进行内存转储后,我意识到堆上有很多对象并导致内存泄漏。我想这是因为我没有处理集线器连接,因为主要的罪魁祸首之一是 Microsoft.AspNet.SignalR.Transports.LongPollingTransport,在玩弄之后堆上有超过一千个对象网站大约一个小时(做一些会创建这些 SignalR 消息的事情)。

所以我认为处理 HubConnection 会解决问题:

using (HubConnection hubConnection = this.CreateHubConnection())
{
if (hubConnection != null)
{
IHubProxy hubProxy = this.StartConnection(hubConnection);
if (hubProxy != null && hubConnection.State == ConnectionState.Connected)
{
await hubProxy.Invoke("MessageClients", messageArgs);
}
}
}

private HubConnection CreateHubConnection()
{
// do some basic auth set up
HubConnection hubConnection = new HubConnection(this.serverUrl);
hubConnection.Headers.Add('authToken', basicAuth);
return hubConnection;
}

private IHubProxy StartConnection(HubConnection hubConnection)
{
IHubProxy hubProxy = hubConnection.CreateHubProxy(this.hubName);
Task t = Task.Run(() => hubConnection.Start(new LongPollingTransport())
t.WaitAndUnwrap();
return hubProxy;
}

但是在运行该进程并将 WinDbg 附加到它之后,当我执行 -!dumpheap -stat -type Microsoft.AspNet.SignalR.Transports 时,我再次看到 Microsoft.AspNet.SignalR .Transports.LongPollingTransport 堆 + 内存上的对象具有相似的高数字。 using 语句不应该导致 HubConnection 被释放并因此从堆中移除吗?我应该如何修复此内存泄漏?

最佳答案

事实证明,处理集线器连接确实有效。我混淆了两个概念:处置非托管资源和从堆中删除对象。

我认为当 HubConnection 对象的 using 语句完成时(即,在 HubConnection 上调用 dispose 时),WinDbg 将不再在内存中显示该对象倾倒。但是由于内存转储是基于堆上的内容,并且由于处理对象不会从堆中删除对象(只是允许它被垃圾收集器释放和删除),它仍然显示在 WinDbg 中。

在垃圾收集器完成工作之前,我更多地使用了该应用程序,并发现对象稍后被删除了。

我还应该注意,我最初的问题强调了 Microsoft.AspNet.SignalR.Transports.LongPollingTransport 类型,那是因为我也没有处理 LongPollingTransport 对象(当我执行 hubConnection.Start(new LongPollingTransport()) 时。所以我的代码现在如下所示:

using (HubConnection hubConnection = this.CreateHubConnection())
{
if (hubConnection != null)
{
using (LongPollingTransport lpTransport = newLongPollingTransport())
{
IHubProxy hubProxy = this.StartConnection(hubConnection, lpTransport);
if (hubProxy != null && hubConnection.State == ConnectionState.Connected)
{
await hubProxy.Invoke("MessageClients", messageArgs);
}
}
}
}

private HubConnection CreateHubConnection()
{
// do some basic auth set up
HubConnection hubConnection = new HubConnection(this.serverUrl);
hubConnection.Headers.Add('authToken', basicAuth);
return hubConnection;
}

private IHubProxy StartConnection(HubConnection hubConnection, HttpBasedTransport transport)
{
IHubProxy hubProxy = hubConnection.CreateHubProxy(this.hubName);
Task t = Task.Run(() => hubConnection.Start(transport));
t.WaitAndUnwrap();
return hubProxy;
}

关于c# - 即使处置了集线器连接,也不会从堆中删除 SignalR 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46166934/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com