首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GC.Collect()和Finalize

GC.Collect()和Finalize
EN

Stack Overflow用户
提问于 2012-12-19 14:46:52
回答 5查看 14.9K关注 0票数 45

好的,当GC将对象标识为垃圾时,它会隐式地调用对象上的Finalize方法。但是如果我做了一个GC.Collect()会发生什么呢?终结器还在执行吗?有人问我这个问题,我回答“是”,然后我想:“这完全正确吗?”

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-12-19 15:03:45

好的,众所周知,当GC将对象标识为垃圾时,它会隐式调用对象上的Finalize方法。

不不不。这是不为人所知的,因为要成为知识,一种陈述必须是真实的。那句话是假的。垃圾收集器不运行终结器,因为它跟踪,不管它是运行自己还是调用Collect--终结器线程在跟踪收集器找到垃圾之后运行终结器,并且在调用Collect时异步发生。(正如另一个答案所指出的那样,如果发生这种情况,它可能不会发生。)也就是说,您不能依赖在控件从Collect返回之前执行的终结器线程。

下面是一个过于简化的草图,说明它的工作原理:

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

正如我所说的,这是过度简化的;终结器队列工作的具体细节要比这要复杂一些。但这个想法已经足够广泛了。这里的实际结果是,您不能假设调用Collect也运行终结器,因为它不运行。让我再重复一次:垃圾收集器的跟踪部分执行而不是运行终结器Collect只运行收集机制的跟踪部分。

如果要确保所有终结器都已运行,则在调用Collect后调用名称恰当的Collect。这将暂停当前线程,直到终结器线程抽出时间清空队列。如果您想确保那些最终完成的对象能够回收它们的内存,那么您将不得不第二次调用Collect

当然,毫无疑问,您应该只为调试和测试目的而这样做。在生产代码中,不要在没有一个非常、非常好的理由的情况下做这种无稽之谈。

票数 76
EN

Stack Overflow用户

发布于 2012-12-19 14:56:25

其实答案是“视情况而定”。实际上,有一个执行所有终结器的专用线程。这意味着对GC.Collect的调用只触发此进程,所有终结器的执行都将被异步调用。

如果您想等到所有终结器都被调用时,可以使用以下技巧:

代码语言:javascript
复制
GC.Collect();
// Waiting till finilizer thread will call all finalizers
GC.WaitForPendingFinalizers();
票数 15
EN

Stack Overflow用户

发布于 2012-12-19 14:55:22

是的,但不是马上。这段摘录来自垃圾收集:微软.NET框架中的自动内存管理(MSDN杂志) (*)

“当应用程序创建新对象时,新运算符将从堆中分配内存。如果对象的类型包含points方法,则将指向该对象的指针放置在终结队列中。终结队列是垃圾收集器控制的内部数据结构。队列中的每个条目指向一个对象,该对象应该在回收对象的内存之前调用其points方法。 当GC发生时..。垃圾收集器扫描终结队列,查找指向这些对象的指针。当找到指针时,指针将从终结队列中移除并附加到可自由队列(发音为“F-可访问”)。可自由队列是由垃圾收集器控制的另一个内部数据结构。可释放队列中的每个指针都标识一个可以调用其Finalize方法的对象。 有一个专门用于调用Finalize方法的特殊运行时线程。当可自由的队列是空的(通常是这样的),这个线程就会休眠。但是当条目出现时,这个线程会唤醒,从队列中删除每个条目,并调用每个对象的Finalize方法。因此,您不应该在Finalize方法中执行任何对正在执行代码的线程作出任何假设的代码。例如,避免访问Finalize方法中的线程本地存储。“

(*)自2000年11月起,情况可能会有所改变。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13954829

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档