【问题标题】:How soon after disposing is memory available?处理后多久可以使用内存?
【发布时间】:2015-06-15 13:05:15
【问题描述】:

GC 运行后是瞬时的吗?

我在运行我正在处理的应用程序时使用 perfmon 监控内存(可用 MBytes)。当我加载文件时,我可以看到可用 MBytes 按预期下降,但当我关闭它们时它并没有回升,所以我想知道我是否没有正确处理,或者是否还有其他影响这一点的东西。

加载文件时:

  • 内容存储在某些对象中
  • 创建了一个新的 UserControl 实例
  • 创建了一个新的 TabPage
  • UserControl 已添加到 TabPage
  • TabPage 被添加到 TabControl

阅读 SO,我发现可能导致内存泄漏的最常见的事情之一不是取消订阅事件处理程序,因此我确保我在 UserControl 的 dispose 方法中做到了这一点。我订阅了 TabControl 的“RemovingTab”事件,但 TabPages 本身没有附加的处理程序。

关闭文件时,我删除对象的存储实例并在 UserControl 和 TabPage 上调用 dispose。我尝试运行 CLR 分析器(我没有任何经验),它说没有运行 GC。

【问题讨论】:

  • "...它说没有 GC 运行"。这就是你的答案。 GC 在需要时运行。您不太可能有内存泄漏。
  • 内存在 GC 运行时可用。如果 GC 没有理由运行,则它不会运行。如果您愿意,可以使用GC.Collect() 手动运行 GC。

标签: c# winforms user-controls garbage-collection


【解决方案1】:

另一个没有被释放的常见内存来源是持有非托管资源,打开的文件就是一个例子。

在 GC 清理所有正在使用它的内存后,内存就可用了。并非每次 GC 运行都会导致内存被释放。任何在至少一次 GC 运行中幸存下来的对象最终都可以存活很长时间,因为它不再处于第 0 代——这些对象最终可能会一直存在,直到应用程序实际需要比当前可用内存更多的内存。大型对象(据我记得大于 85kb)存储在大型对象堆中,这也不是每次 GC 运行的一部分。

最好的办法是查看实际保存内存的内容。使用 Visual Studio 性能工具或尝试 PerfView。一旦您知道实际持有内存的是什么,您就可以更好地弄清楚如何释放它。

【讨论】:

    【解决方案2】:

    GC 运行后是瞬时的吗?

    没有。事实上,根据特定应用程序的内存压力,GC 可能不会在应用程序的整个生命周期内释放任何内存。

    阅读 SO 我发现可能导致内存泄漏的最常见的事情之一不是取消订阅事件处理程序,因此我确保我在我的 UserControl 的 dispose 方法中这样做了。

    是的,这是一个常见的原因。

    关闭文件时,我删除对象的存储实例并在 UserControl 和 TabPage 上调用 dispose。我尝试运行 CLR 分析器(我没有任何经验),它说没有 GC 运行。

    GC 非常擅长做它应该做的事情,它已经被微调到极端。如果它不运行,可能是因为它决定不需要运行。因此,何时GC 释放内存由GC 决定,如果我没记错的话,是实现定义的,所以它不是你可以依赖的上。

    最后但同样重要的是,IDisposable 模式无论如何都不是用于回收内存的确定性模式。这绝对是不是该模式的目标。

    【讨论】:

      猜你喜欢
      • 2018-09-29
      • 2013-01-22
      • 2015-01-10
      • 2011-09-11
      • 1970-01-01
      • 2017-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多