如何判断什么/谁阻止对象被垃圾收集(C#)

时间:2015-02-20 23:00:32

标签: c# garbage-collection

我已经在C#/ WPF应用程序上工作了一段时间,我已经到了我认为我的一些对象没有像我期望的那样被垃圾收集的程度。

我是如何做出这个决定的?

我已经在我希望被垃圾收集的类中添加了一个断点的终结器。我运行我的应用程序并触发一系列事件,这些事件将a)创建对象然后b)导致对象被谴责(理论上)。例如,我打开一个对话框,然后关闭它,等等。我的终结器没有被调用。

为了更加确定GC没有花费太长的时间,或者某些对象以某种方式被提升为老一代,因此没有以相同的速率收集,我甚至创建了一个定期强制垃圾收集的线程,即:

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

仍未击中终结器断点。在这一点上,我很确定有一些参考可以阻止这些对象被收集,但我不能为我的生活决定什么。

所以我的问题是双重的:

  1. 根据我的测试,我的结果是否有效?
  2. 若有,有一些 我可以用来确定对象引用的机制或工具 (即对象参考链的直观表示)?
  3. 提前致谢!

2 个答案:

答案 0 :(得分:2)

这可能不是你问题的准确答案,因为我看不到你的代码 - 但我最常见的是,当一个对象通常没有收集垃圾时,因为我忘了取消订阅某个地方的事件。订阅活动时,您会创建一个参考,以防止收集您的课程。

另一方面,垃圾收集器是一个非常难以预测的过程。我记得在某个地方读过,即使你打电话给GC.Collect,它也不能保证你的未参考课程会立即被收集。

答案 1 :(得分:0)

通过调用GC.CollectGC.WaitForPensingFinalizers,您确保终结器将启动,但您还需要确保此代码正在调用。 Breakingpoint it (或者更确切地说,是WaitForPendingFinalizers之后的方法闭包)以确保代码正在执行。

由于这是一个WPF项目,因此插入一个"调试按钮"也可能会有所帮助。通过在您正在处理的任何视图中使用PreviewKeyDown,可以查找特定密钥,然后在其他无操作if中查找断点。将垃圾收集代码放在这里应该同样确保代码正在执行。

如上所述,事件处理程序也可以是硬引用,因此请注意您在任何地方使用事件,并意识到WPF会挂钩PropertyChanged