为什么我的Windows没有进行垃圾回收?

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

以下是正在发生的相当标准的用例:

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

因此,在任何给定时间,我都会持有2-3个窗口在内存中,而实际上我只需要一个窗口。我甚至在这些窗口的关闭事件中添加了处置代码,将我能想到的所有引用都设置为null。

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

谢谢!

PS: 我已经检查了这个链接,但它没有解决问题。

编辑: 问题在于用户遇到了System.OutOfMemoryExceptions。

2个回答

3
我通过两个更新成功解决了这个问题。首先,我在我的子窗口上使用了Telerik控件。Telerik控件必须跟踪根可视元素,因此如果它们仅在子窗口上实例化,则在每次实例化时,它们都会假设子窗口是根可视元素并分配一个静态引用。通过在我的主应用程序窗口上实例化Telerik控件,该窗口被设置为静态引用中的根可视元素。
我进行的第二个更新是将每个子窗口的所有者分配为我的主应用程序窗口。在执行此操作并进行分析后,我发现子窗口不再被设置为GC根。
现在,我的子窗口在关闭后会自动进行垃圾回收,只要新的内存被请求以供另一个窗口使用即可。

2

一般而言,垃圾回收器(GC)有自己的生命周期。释放资源只是通知它不再需要这些资源。由于性能限制和平台特定实现,垃圾回收需要一定时间。

让开发者更容易的事情有时会损害性能。这就是为什么在C/C++中,可以拥有内存并随意使用new/delete。即使在那里也有池和其他技术,因为new/delete不便宜。

最后,您需要确定架构中的问题所在。为什么这对您是个问题?内存不足?交换?本地或服务器端?等等。


通常情况下,GC有自己的生命周期。即使我调用GC.Collect()也无法释放资源。好像有些东西将这些资源固定在那里,但我不知道是什么在做这件事。我没有任何静态引用这些应该被收集的对象 - 我已经通过分析器验证了这一点。我认为问题与每个窗口都是GC根有关,但由于它似乎内置于WPF中,我不知道该怎么办。 - Jake
从您的原始帖子中看来,资源被释放了,但在调用GC.Collect()之后并不立即释放。是这样吗? - Zepplock
GC.Collect() 似乎无法释放资源。只有在很长一段时间后才会释放它们,这与我不调用此方法时释放它们的时间相同。 - Jake
@Jake(和其他人)Collect并不是你想象中的那样。要真正强制释放内存,你需要调用WaitForPendingFinalizers。https://dev59.com/pGYr5IYBdhLWcg3wGmiq#13955187 - StayOnTarget

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接