未收集垃圾的对象
我正在使用第三方组件,但发现一些资源未释放的问题。 该组件使 Windows 创建 UDP 套接字的句柄(“\Device\Udp”以及“\Device\Afd”)。 如果我允许程序执行并取消引用第三方对象,我假设像我过去使用过的所有 .NET 对象一样,该对象将被垃圾收集。 但是,Process Explorer 显示“\Device\Udp”句柄将无限期地保留,直到实际进程被终止(或者在有问题的应用程序的情况下:应用程序池被回收。
此外,如果我手动调用对象的 Dispose() 方法,则句柄将被释放。这是我已经进行了修复,但我只是好奇为什么需要它。组件的构建者是否可能做了一些事情或设置了一些属性来阻止垃圾收集器调用对象的破坏
? 后该过程不会结束。
完成
for (int i = 0; i < n; i++)
{
Snmpmgr mgr = new Snmpmgr();
mgr.Timeout = 10;
mgr.ObjCount = 1;
mgr.ObjId[1] = ".1.3.6.1.2.1.1.1.0";
try
{
mgr.SendGetRequest(); // Handle shows up in ProcExplorer after this call
}
catch (Exception ex)
{
throw new TimeoutException("Error contacting CMTS.");
}
} // end of for... obj referenced by mgr never garbage collected
有帮助,我发布了下面的代码。该代码在 Forms 应用程序中使用,因此在 while循环 已发布):
for (int i = 0; i < n; i++)
{
Snmpmgr mgr = new Snmpmgr();
mgr.Timeout = 10;
mgr.ObjCount = 1;
mgr.ObjId[1] = ".1.3.6.1.2.1.1.1.0";
try
{
mgr.SendGetRequest(); // Handle shows up in ProcExplorer after this
}
catch (Exception ex)
{
throw new TimeoutException("Error contacting CMTS.");
}
mgr.Dispose(); // UDP Socket Handle freed... not sure that's how to spell free + ed :)
}
提前感谢您的帮助
。
I have a third party component I'm using and I'm seeing some issues with resources not being released. The component causes windows to create a handle to a UDP socket ("\Device\Udp" as well as "\Device\Afd"). If I allow the program to execute and dereference the third party object, I assumed that like all .NET objects I've worked with in the past, the object will get garbage collected. However, Process Explorer is showing that the "\Device\Udp" handles are being kept indefinitely until the actual process is killed (or in the case of the app in question: app pool is recycled.
Furthermore, if I manually call the Dispose() method of the object, then the handles are released. This is the fix I have in place, but I'm just curious about why it is needed. Is it possible that the builders of the componenet have done something or set some attribute which prevents the garbage collector from calling the destructing on the object?
If it helps, I have posted the code below. The code was used in a Forms application, so the process does not end after the while loop completes.
Code that does not work (100 handles created indefinitely):
for (int i = 0; i < n; i++)
{
Snmpmgr mgr = new Snmpmgr();
mgr.Timeout = 10;
mgr.ObjCount = 1;
mgr.ObjId[1] = ".1.3.6.1.2.1.1.1.0";
try
{
mgr.SendGetRequest(); // Handle shows up in ProcExplorer after this call
}
catch (Exception ex)
{
throw new TimeoutException("Error contacting CMTS.");
}
} // end of for... obj referenced by mgr never garbage collected
Code that does work (handles created and released):
for (int i = 0; i < n; i++)
{
Snmpmgr mgr = new Snmpmgr();
mgr.Timeout = 10;
mgr.ObjCount = 1;
mgr.ObjId[1] = ".1.3.6.1.2.1.1.1.0";
try
{
mgr.SendGetRequest(); // Handle shows up in ProcExplorer after this
}
catch (Exception ex)
{
throw new TimeoutException("Error contacting CMTS.");
}
mgr.Dispose(); // UDP Socket Handle freed... not sure that's how to spell free + ed :)
}
Thanks in advance for your help.
Chris
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
事实上,您确实在
Snmpmgr
类上实现了一个析构函数来释放套接字句柄,对吗? ...否则,如果您不通过Dispose()
显式执行此操作,GC 就不知道需要执行一些工作来释放资源。You did in fact implement a destructor on the
Snmpmgr
class to release the socket handle, right? ... otherwise the GC does not know there is some work to be done to release resources if you do not do it explicitly throughDispose()
.也许您可以将 mgr.Dispose() 放在“finally”子句中,位于 try/catch 块之后。
Perhaps you can put mgr.Dispose() in your "finally" clause, after your try/catch block.
调用 Dispose 是正确的做法。 某些对象使用非托管资源(如果您使用套接字,则很可能是这种情况)。 精确地公开 Dispose 方法,以便对象可以正确地释放其非托管资源。 每当您使用实现 IDisposable 的对象时,都应该在使用完毕后调用 Dispose。
有关 IDisposable 的更多详细信息:如何在 .net 中处置类?
Calling Dispose is the proper thing to do. Some objects use unmanaged resources (and if you're working with sockets, it's likely the case). The Dispose method is exposed precisely so that the object can properly deallocate its unmanaged resources. Any time you use an object that implements IDisposable, you should call Dispose when you're done with it.
For more detail about IDisposable: How to dispose a class in .net?
这就是 Dipose() 方法的要点。 由于人们永远无法知道析构函数何时被调用,因此您应该使用 Dispose 来释放非托管资源。
正如 MiffTheFox 所说,您应该将代码放在“using”块中。 当代码执行到“using”块末尾时,将自动调用 Dipose()。
That's the point about the Dipose() method. Since one can never know when the destructor will be called, you should use Dispose to release unmanaged resources.
As MiffTheFox said, you should put your code inside an 'using' block. When the code execution reaches the end of the 'using' block, Dipose() will be called automatically.
您在第二个示例中使用了 mgr.Dispose 调用。 我会认为 mgr 是 IDisposable 吗?
在这种情况下,您需要使用 using 块:
You used a mgr.Dispose call in the second example. I'll take it mgr is an IDisposable?
In that case, you need to use a using block: