如果已经调用了一个对象的终结器,我是否可以100%确定它之后将被删除?

时间:2016-07-05 14:50:26

标签: c# wpf visual-studio-2015 garbage-collection finalizer

我有一个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确实(刚刚再次检查过)。

3 个答案:

答案 0 :(得分:0)

不,这就是为什么我们有GC.WaitForPendingFinalizers的方法:

  

当垃圾收集器找到可以回收的对象时,它   检查每个对象以确定对象的最终确定   要求。如果对象实现了终结器并且未禁用   通过调用SuppressFinalize来完成,将对象放在一个   标记为已准备好进行最终化的对象列表。垃圾   collector为此列表中的对象调用Finalize方法   从列表中删除条目。这种方法阻止所有   终结者已经完成了。

     

运行终结器的线程未指定,因此没有   保证此方法将终止。但是,这个帖子可以   在WaitForPendingFinalizers时被另一个线程中断   方法正在进行中。例如,您可以启动另一个线程   等待一段时间然后中断此线程,如果这样   线程仍然被暂停。

答案 1 :(得分:0)

当垃圾收集器将对象识别为未使用的对象时,它将被垃圾收集器调用。但是不保证,将收集该对象。如果对象引用了未关闭的非托管资源,则可能会发生这种情况。

检查该课程中使用的资源。其中一些必须仍然开放。

答案 2 :(得分:0)

没有。在完成对象后,仍然可以对非托管资源进行一些引用。检查内部泄漏。