我有一个WPF应用程序,允许用户打开,关闭并重新打开任意数量的子窗口。
使用VS2015的集成内存分析器我发现某种类型的子窗口,我们称之为 ProblematicChildWindow ,在关闭后总是保留在内存中,因此它的实例会在频繁关闭时加起来并重新开始行动。不幸的是,我无法在最小的应用程序中重现问题(一切正常)。
我知道WPF的常见内存泄漏情况,我得出的结论是分析器必定是错误的。所以我将以下代码添加到有问题的类中:
~ProblematicChildWindow()
{
using (StreamWriter sw = File.CreateText("d:\\garbagecollection.txt"))
{
sw.WriteLine(DateTime.Now.ToShortTimeString() + " garbage collected.");
}
}
现在奇怪的是:
打开和关闭 ProblematicChildWindow 的实例并强制进行垃圾回收后,我在D:\文件夹中找到一个新文件“garbagecollection.txt”,但是
VS2015的内存分析器告诉我内存中仍然存在 ProblematicChildWindow 的实例!
我的问题:由于实例显然已被垃圾收集(因为已经调用了终结器),我可以确定已释放占用的内存吗?
在这种情况下,VS2015的内存分析器似乎有一个错误。
更新: .NET Memory Profiler告诉我关闭后内存中没有实例。但是VS2015确实(刚刚再次检查过)。
答案 0 :(得分:0)
不,这就是为什么我们有GC.WaitForPendingFinalizers
的方法:
当垃圾收集器找到可以回收的对象时,它 检查每个对象以确定对象的最终确定 要求。如果对象实现了终结器并且未禁用 通过调用SuppressFinalize来完成,将对象放在一个 标记为已准备好进行最终化的对象列表。垃圾 collector为此列表中的对象调用Finalize方法 从列表中删除条目。这种方法阻止所有 终结者已经完成了。
运行终结器的线程未指定,因此没有 保证此方法将终止。但是,这个帖子可以 在WaitForPendingFinalizers时被另一个线程中断 方法正在进行中。例如,您可以启动另一个线程 等待一段时间然后中断此线程,如果这样 线程仍然被暂停。
答案 1 :(得分:0)
当垃圾收集器将对象识别为未使用的对象时,它将被垃圾收集器调用。但是不保证,将收集该对象。如果对象引用了未关闭的非托管资源,则可能会发生这种情况。
检查该课程中使用的资源。其中一些必须仍然开放。
答案 2 :(得分:0)
没有。在完成对象后,仍然可以对非托管资源进行一些引用。检查内部泄漏。