我需要在内存使用方面优化我的应用程序。所以我用.net性能分析器...... 但是我的应用程序中的一些引用仍然存在,即使我强行收集它也不会被GC收集。
活着的引用是"终结句柄"类型。 我不知道如何删除这种参考....请帮忙。
答案 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}}退出块的范围时。