【问题标题】:Why aren't my windows getting garbage collected?为什么我的窗户没有被垃圾收集?
【发布时间】:2011-06-14 22:14:09
【问题描述】:

我有一个标准的 CRUD 应用程序,可以处理大量数据。不同的窗口使用 Linq-To-SQL 访问不同的表,每个窗口本质上都有一个网格,其中的单元格绑定到我正在显示的对象。

这是正在发生的事情的一个非常标准的用例:

  1. 打开窗口A
  2. 关闭窗口 A - 窗口 A 现在仍在内存中,但不再可见。
  3. 打开窗口 B
  4. 关闭窗口 B - 窗口 A 和 B 现在都在内存中,并且都不可见。
  5. 打开窗口C
  6. 为 Window C 检索数据时,会释放 Window A 的资源。

因此,在任何给定时间,我都会在内存中保存 2-3 个窗口,而我真正应该拥有的只是一个。我什至在这些窗口的关闭事件中添加了处理代码,它将我能想到的所有引用设置为空。

我尝试使用 ANTS 内存分析器,我注意到每个窗口都设置为 GC 根。有没有办法禁用此行为或以某种方式强制 GC 从这些窗口收集?

谢谢!

PS:我检查了this link 并没有解决问题。

编辑:问题是用户得到 System.OutOfMemoryExceptions。

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    我能够通过两次更新来解决这个问题。首先,我在我的子窗口上使用 Telerik 控件。 Telerik 控件必须跟踪根视觉对象,因此如果它们仅在子窗口上实例化,那么在每次实例化时,它们都假定子窗口是根视觉对象并为其分配静态引用。通过在我的主应用程序窗口上实例化一个 Telerik 控件,该窗口被设置为静态引用中的根视觉对象。

    我所做的第二次更新是将每个子窗口的所有者指定为我的主应用程序窗口。完成此操作并进行分析后,我发现子窗口不再被设置为 GC 根。

    现在我的子窗口在关闭后会自动收集垃圾,只要为另一个窗口请求新内存。

    【讨论】:

      【解决方案2】:

      一般来说,GC 有自己的生活。通过释放资源,您只需通知它不再需要资源。由于性能限制和平台特定的实现,垃圾收集需要一些时间。

      是什么让开发人员的生活更轻松 - 有时会损害性能。这就是为什么在 C/C++ 中 可以根据需要拥有内存和新建/删除。即使有池和其他技术,因为新/删除并不便宜。

      最后,您需要确定架构中的问题。为什么这对你来说是个问题?失忆了?交换?在本地还是在服务器上?等等。

      【讨论】:

      • "一般来说,GC 有自己的生活。" - 即使我调用 GC.Collect() 它也不会释放资源。好像有什么东西将这些资源固定在适当的位置,但我不知道是什么做的。我没有对应该收集的这些对象的任何静态引用——我已经用探查器验证了这一点。我假设这个问题与每个窗口都是 GC 根有关,但我不知道该怎么做,因为它似乎内置于 WPF 中。
      • 从您的原始帖子看来,资源已被释放,但不是在调用 GC.Collect() 后立即释放。是这样吗?
      • GC.Collect() 似乎没有释放资源。它们直到很晚才被释放,大约在我不调用此方法时它们被释放的时间。
      • @Jake(和其他人)Collect 不会像您认为的那样做。要真正强制释放内存,您需要调用 WaitForPendingFinalizers。 stackoverflow.com/a/13955187/3195477
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-25
      相关资源
      最近更新 更多