c# - GC.Collect() 和完成

标签 c# .net garbage-collection finalizer

好的,众所周知,当 GC 将对象识别为垃圾时,它会隐式调用对象上的 Finalize 方法。但是如果我执行 GC.Collect() 会发生什么? finalizer 是否仍然执行?有人问我这个问题,我回答"is",然后我想:“完全正确吗?

最佳答案

Ok, it's known that GC implicitly calls Finalize methods on objects when it identifies that object as garbage.

不不不。这不是已知,因为要成为知识,一个陈述必须是。该声明是错误的垃圾收集器在跟踪时不会运行终结器,无论它是自己运行还是调用 Collect终结器线程在跟踪收集器找到垃圾后运行终结器,并且相对于对 Collect 的调用,这发生异步。 (如果它真的发生了,它可能不会发生,正如另一个答案所指出的那样。)也就是说,您不能依赖在控制从 Collect 返回之前执行的终结器线程。

这是它如何工作的一个过于简单的草图:

  • 当收集发生时,垃圾收集器跟踪线程跟踪根源——已知存在的对象,以及它们引用的每个对象,等等——以确定死对象。
  • 具有未决终结器的“死”对象被移动到终结器队列中。 终结器队列是根。因此,那些“死”的对象实际上还活着
  • 终结器线程(通常与 GC 跟踪线程不同)最终运行并清空终结器队列。然后这些对象真正死亡,并被收集到跟踪线程的next 集合中。 (当然,因为他们刚刚从第一次收集中幸存下来,所以他们可能处于更高的世代。)

正如我所说,这过于简单化了;终结器队列如何工作的确切细节比这要复杂一些。但它得到了足够的想法。这里的实际结果是,您不能假设调用 Collect 也会运行终结器,因为它不会。让我再重复一遍:垃圾收集器的跟踪部分运行终结器Collect 只运行垃圾收集器的跟踪部分征集机制。

如果您想保证所有终结器都已运行,请在调用 Collect 之后调用恰当命名的 WaitForPendingFinalizers。这将暂停当前线程,直到终结器线程开始清空队列。如果你想确保那些最终确定的对象回收它们的内存,那么你将不得不 第二次 调用 Collect

当然,不言而喻,您只应出于调试和测试目的执行此操作。没有真正、真的充分的理由,永远不要在生产代码中做这种无意义的事情。

关于c# - GC.Collect() 和完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13954829/

相关文章:

c# - 如何从 Canvas 中的隐藏代码打开图像并让用户在此图像上绘图

c# - 在业务层中使用 [DataContract] 标记类是一个糟糕的设计吗?

c# - .net 等同于 htmlunit?

garbage-collection - 防止 CLR 中早期垃圾回收的最佳方法

java - 除了互斥锁或垃圾收集之外还有哪些机制可以减慢我的多线程 Java 程序的速度?

c# - 实例化对象不移动

c# - 在 Azure Service Fabric 中运行时更改配置

c# - String.Replace 和 Regex.Replace 不适用于 IComparer 中的特殊字符

sql - 标签 'N' 已被声明。标签名称在查询批处理或存储过程中必须是唯一的

java - GC 字符串实习生