垃圾收集器是否受益于对Collect和WaitForPendingFinalizers()的多次调用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了垃圾收集器是否受益于对Collect和WaitForPendingFinalizers()的多次调用?相关的知识,希望对你有一定的参考价值。

我发现这个在线代码是在取消初始化Excel Interop对象后附加的:

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

这是对DRY的准违反(以口吃的方式连续两次调用GC.Collect()和GC.WaitForPendingFinalizers())有什么用处,或者只是浪费时间?

答案

这来自Microsoft documentation站点上的示例程序。

   //Force garbage collection.
   GC.Collect();

   // Wait for all finalizers to complete before continuing.
   // Without this call to GC.WaitForPendingFinalizers, 
   // the worker loop below might execute at the same time 
   // as the finalizers.
   // With this call, the worker loop executes only after
   // all finalizers have been called.
   GC.WaitForPendingFinalizers();

当垃圾收集器找到可以回收的对象时,它会检查每个对象以确定对象的终结要求。如果一个对象实现了一个终结器并且没有通过调用SuppressFinalize来禁用终结,那么该对象将放在一个标记为准备完成的对象列表中。垃圾收集器为此列表中的对象调用Finalize方法,并从列表中删除条目。此方法将阻塞,直到所有终结器都运行完成。

运行终结器的线程未指定,因此无法保证此方法将终止。但是,当WaitForPendingFinalizers方法正在进行时,此线程可能被另一个线程中断。例如,您可以启动另一个等待一段时间的线程,然后在此线程仍处于挂起状态时中断此线程。

据我所知,没有明确的迹象表明两次调用它的好处。

另一答案

垃圾收集器是否受益于多个调用...

你不是这样做有利于GC,远非如此,你这样做是为了强制Excel.exe终止。它不能停止,直到所有的interop包装器(RCWs)完成。单个GC.Collect()调用足以设置该列车运动。

随后的GC.WaitForPendingFinalizers()调用是可选的。没有什么理由想要等到它们完成。在一个表现良好的程序中,这最多只能在几毫秒内完成。如果拥有这些interop包装器的线程将要终止,那么这一点非常重要。这并不常见。如果您不确定那么使用它没有错。

第二次收集+等待呼叫没用。 RCW非常小,因此Collect调用不会释放任何有用的内存量。等等无法等待。

放置此代码往往很重要。如果它出现在使用Excel接口的相同方法中,则在附加调试器时它将不会执行任何操作。将它放在方法的调用者中是最好的。 this post解释了为什么调试器起作用。

另一答案

简短的回答是,不,你不应该叫它两次。

现在,让我们深入挖掘一下。 GC使用基于生成的方法。也就是说 - 堆被分成块,用于优化GC,因此它实际上在较小的内存区域上运行。您可以了解有关GC如何工作here的更多信息。

当GC运行时,它会回收当前一代中的所有对象,这些对象没有强*引用(* - 可以使用System.WeakReference类型来引用对象,同时允许GC回收它)。在垃圾收集中幸存下来的那些对象被移动到下一代。如果下一代足够,GC也会在它上面运行 - 进一步移动幸存的对象。话虽如此,你可以看到第二次运行GC的可能性几乎没有差别。

但是,在负载很重的情况下,对象的创建速度非常快,两次后续调用之间的时间间隔就足够了(取决于线程的状态,优先级 - 调用的时间)来创建足够的对象,可以添加一些记忆的重量。在那种情况下,后续调用可以产生影响并清理大量内存。虽然这种情况有可能发生,但实际情况并非如此。原因是,如果有这样的负载,它可能会继续,所以调用GC两次将没有太大的区别......

以上是关于垃圾收集器是否受益于对Collect和WaitForPendingFinalizers()的多次调用?的主要内容,如果未能解决你的问题,请参考以下文章

对 .NET 垃圾收集器的质疑

跨 AppDomain 边界的垃圾收集对象

BigQuery 中的表视图是不是受益于分区/集群优化?

是否可以强制对象的垃圾收集?(java)

面试官:你对JVM垃圾收集器了解吗?13连问你是否抗的住!

面试官:你对JVM垃圾收集器了解吗?13连问你是否抗的住!