何时在.NET中使用GC.Collect()?

时间:2011-03-21 20:50:54

标签: c# .net garbage-collection

  

可能重复:
  When is it acceptable to call GC.Collect?

据我所知,CLR会为您完成所有这些垃圾回收,但是有理由手动调用GC.Collect()吗?

是否在关闭文件,处理图像资源或非托管资源时,应该调用GC.Collect()以立即快速清理未使用的内存?

5 个答案:

答案 0 :(得分:8)

答案 1 :(得分:5)

  

对于关闭文件,处置图像资源或非托管资源的情况,您应该调用GC.Collect()来快速清理未使用的内存吗?

不,不是真的。这通常通过IDisposable处理。

直接调用GC.Dispose()的理由很少,这样做往往会造成很大的伤害,因为它会干扰.NET中GC的内部启发式。然而,当它有用时,很少发生。

例如,如果您的操作是一项使用大型对象图的罕见操作,并且您知道之后您将“空闲”,那么可能想要调用{{ 1}}之后立即释放对象使用的内存。话虽如此,这通常最好由系统来处理。

在大多数情况下,我发现GC.Collect最有用的方案是进行调试。它可以帮助您保证您没有泄漏,因为它允许您强制完整的Gen2集合。

答案 2 :(得分:3)

我通常使用GC.Collect()将堆置于一个大多数已知的状态。例如,在进行基准测试时,您需要确保从已知状态开始每次运行,并GC.Collect()对此有所帮助。

应该用于处理非托管资源 - 为此您应该使用using或手动调用Dispose

答案 3 :(得分:3)

我可以想到GC.Collect() 可能有用的两种情况:

  • 在单元测试中。在一些测试之前和之后调用GC.Collect()以发现潜在的内存泄漏。在这种情况下,请考虑使用GC.WaitForPendingFinalizers(),因为终结器在单独的线程中执行。这意味着具有终结器的类在调用GC.Collect()后不会立即释放所有资源。

  • 在像Windows服务这样长时间闲置的漫长生活过程中。在闲置之前呼叫GC.Collect()。原因:如果进程空闲,垃圾收集器将不会启动,因此在空闲时间内不会释放未使用的内存。

不应该为了“立即快速清理未使用的内存”而调用<{GC.Collect()。强制释放内存并不会降低由活动垃圾回收引起的整体性能。

答案 4 :(得分:1)

我唯一一次在代码中使用它的时候没有专门比较两种或更多种不同方法的内存使用情况,有以下情况:

在一个Web应用程序中(因此,长期运行),有一些非常大的集合,通常一天最多可以重建几次,通常不那么频繁。

该集合中的几个对象是等价的,因此可以通过将对一个这样的对象的引用替换为对另一个对象的引用来保存大量内存(在构建集合之后,在使用时是只读的,因此别名涉及是安全的)。所以首先要构建集合,但随后它会缩小,会杀死许多对象。

这意味着每秒被摧毁的物体数量突然增加,至少几个小时内不会再发生这种情况。因此,GC无法正确判断所需的收集量,并且即将需要内存来构建第二个大型集合。因此,每千次清理操作进行手动收集确实对性能产生了积极影响(足以有时从应用程序崩溃到第三个集合,到可靠)。

进行了大量测量以确保在这种情况下确实有益。

使这一点受益的两个因素是:

  1. 发生了很多物体死亡事件。
  2. 导致此问题的事件在应用程序的生命周期中很少见。
  3. 如果两者都没有,那么手动调用将是不必要的。没有很多对象死亡,没有任何意义,如果它在应用程序的生命周期中并不罕见,那么GC可以自我调整以应对。