终结句柄保留在内存中。如何删除此引用?

时间:2016-11-27 11:46:01

标签: c# reference garbage-collection finalization

我需要在内存使用方面优化我的应用程序。所以我用.net性能分析器...... 但是我的应用程序中的一些引用仍然存在,即使我强行收集它也不会被GC收集。

活着的引用是"终结句柄"类型。 我不知道如何删除这种参考....请帮忙。

this picture is what I mean

1 个答案:

答案 0 :(得分:2)

这不是内存泄漏,只是AMProLibrary作者的草率编码。

正如您所观察到的,分析器告诉您引用的对象是“Finalization Handle”类型。这意味着它来自终结器队列。终结器队列是.NET垃圾收集器用于保存实现终结器方法的所有对象的内容。终结器是用于确保在垃圾收集期间正确释放非托管资源的机制。包含非托管资源的对象实现IDisposable模式,包括Finalize方法,该方法是释放非托管资源的位置。当垃圾收集器处理“可终结”对象(由对象标头中的位值指示)时,它会将它们移动到终结器队列中。在收集过程中,GC会遍历终结器队列并在每个对象上调用Finalize方法。

图书馆的作者显然未能做到的是从GC.SuppressFinalize()方法中拨打Dispose。这通常通过清除对象标头中的“finalizable”位来从终结器队列中删除对象,并指示不需要调用Finalize方法。

出于测试目的,您可以通过调用GC.WaitForPendingFinalizers函数强制终结器运行。例如:

System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect();

但是,您不应该在生产应用程序中实际使用这样的代码。强迫收藏很少有意义。这将证明上述假设的有效性。

通常,您不应该依赖终结器来释放非托管资源。所有实现IDisposable的对象都应该由您的代码明确处理,方法是手动调用Dispose方法,或者最好将其创建包装在using块中,该块将自动调用{ {1}}退出块的范围时。