如果一个对象的终结器被调用了,我是否可以 100% 确定它之后会/将从内存中删除

本文关键字:之后 100% 删除 内存 一个对象 调用 是否 如果 | 更新日期: 2023-09-27 17:55:10

我有一个WPF应用程序,允许用户打开,关闭和重新打开任意数量的子窗口。

使用VS2015的集成内存分析器,我发现某种类型的子窗口,我们称之为ProblemChildWindow,在关闭后总是留在内存中,因此在频繁关闭和重新打开操作的情况下,它的实例会加起来。不幸的是,我无法在最小的应用程序中重现该问题(那里一切正常)。

我知道 WPF 的常见内存泄漏情况,并且得出的结论是探查器一定是错误的。所以我将以下代码添加到有问题的类中:

~ProblematicChildWindow()
{
   using (StreamWriter sw = File.CreateText("d:''garbagecollection.txt"))
   {
      sw.WriteLine(DateTime.Now.ToShortTimeString() + " garbage collected.");
   }
}

现在奇怪的是:

在打开和关闭 ProblemChildWindow 的实例并强制垃圾回收后,我在 D:'' 中找到一个新文件"垃圾收集.txt文件夹,但是

VS2015的内存分析器告诉我,内存中仍然有一个ProblemChildWindow的实例!

的问题:由于实例显然已被垃圾回收(因为已调用终结器),我能确定占用的内存将被释放吗?

在这种情况下,VS2015的内存分析器似乎有一个错误。

更新:.NET 内存性能分析器告诉我,关闭后内存中没有剩余的实例。但是VS2015确实如此(只是再次检查了它)。

如果一个对象的终结器被调用了,我是否可以 100% 确定它之后会/将从内存中删除

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

当垃圾回收器找到可以回收的对象时,它会 检查每个对象以确定对象的完成 要求。如果对象实现终结器并且未禁用 通过调用 SuppressFinalize 完成,对象被放置在 标记为准备完成的对象列表。垃圾 收集器调用此列表中的对象的 Finalize 方法,并且 从列表中删除条目。此方法阻止,直到所有 终结器已运行完成。

运行终结器的线程未指定,因此没有 保证此方法将终止。但是,此线程可以是 被另一个线程打断,而等待挂起终结器 方法正在进行中。例如,您可以启动另一个线程 等待一段时间,然后中断此线程,如果 线程仍处于挂起状态。

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

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

No.完成后,您的对象仍然可以具有对非托管资源的一些引用。检查内部泄漏。