所以GC.Collect()并完成 [英] GC.Collect() and Finalize

查看:152
本文介绍了所以GC.Collect()并完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好了,据了解,GC隐式调用对象的的Finalize 方法时,它识别对象作为垃圾。但是,如果我这样做会发生什么 GC.Collect的()?是终结还是执行?一个愚蠢的问题,也许,但有人问我这个,我回答了是,然后我想:?的是完全正确的

解决方案
  

好了,据了解,GC隐式调用对象的finalize方法,当识别对象为垃圾。

不不不。这是不是的的原因,以便知识的声明必须的真正的。这种说法是的的。 垃圾收集不运行的终结,因为它的痕迹,无论它运行本身,还是你叫收集终结线程运行终结后的跟踪收集器发现垃圾,然后出现这种情况的异步的相对于调用收集。 (如果它发生在所有的,它可能不会像另一个回答指出。)也就是说,你可以不依赖终结器线程控制返回之前执行从上收集

下面是它如何工作的过分简化的草图:

  • 当收集发生在垃圾收集器线程的跟踪追溯的根源 - 已知存活的对象,它们引用的每个对象,等等 - 来确定死亡对象。
  • 在具有挂起终结死的对象被移动到终结队列中。 终结队列是一个根。因此,这些死的对象实际上的还活着
  • 的终结器线程,这通常是一个不同的线程以外的线程的GC跟踪线程,最终运行并清空出终结队列。这些对象进而成为真正的死了,被收集在下一步的收集跟踪线程。 (当然,因为他们只是挺过了第一个集合,他们可能会在一个更高的一代。)

正如我所说的,这是简单化;如何终结队列作品的具体细节更为复杂的比这一点。但它得到足够的整个想法。这里的实际结果是,你不能假设调用收集也运行终结的,因为它没有。让我重复说一次:垃圾收集器的跟踪部分做的没有的运行终结收集只运行收集机制的跟踪的部分。

调用恰当地命名为 WaitForPendingFinalizers 呼叫后收集如果要保证所有的终结已经运行。这将暂停当前线程,直到终结器线程得到周围排空队列。如果你想确保那些完成目标有自己的内存回收,然后你将不得不调用收集 A的第二的时间。

当然,不用说,你只能这样做了调试和测试目的。永远不要做这种无聊的生产code没有一个真正的,的真正的很好的理由。

Ok, it's known that GC implicitly calls Finalize methods on objects when it identifies that object as garbage. But what happens if I do a GC.Collect()? Are the finalizers still executed? A stupid question maybe, but someone asked me this and I answered a "Yes" and then I thought: "Was that fully correct?"

解决方案

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

No no no. That is not known because in order to be knowledge a statement must be true. That statement is false. The garbage collector does not run finalizers as it traces, whether it runs itself or whether you call Collect. The finalizer thread runs finalizers after the tracing collector has found the garbage and that happens asynchronously with respect to a call to Collect. (If it happens at all, which it might not, as another answer points out.) That is, you cannot rely on the finalizer thread executing before control returns from Collect.

Here's an oversimplified sketch of how it works:

  • When a collection happens the garbage collector tracing thread traces the roots -- the objects known to be alive, and every object they refer to, and so on -- to determine the dead objects.
  • "Dead" objects that have pending finalizers are moved onto the finalizer queue. The finalizer queue is a root. Therefore those "dead" objects are actually still alive.
  • The finalizer thread, which is typically a different thread than the GC tracing thread, eventually runs and empties out the finalizer queue. Those objects then become truly dead, and are collected in the next collection on the tracing thread. (Of course, since they just survived the first collection, they might be in a higher generation.)

As I said, that's oversimplified; the exact details of how the finalizer queue works are a bit more complicated than that. But it gets enough of the idea across. The practical upshot here is that you cannot assume that calling Collect also runs finalizers, because it doesn't. Let me repeat that one more time: the tracing portion of the garbage collector does not run finalizers, and Collect only runs the tracing part of the collection mechanism.

Call the aptly named WaitForPendingFinalizers after calling Collect if you want to guarantee that all finalizers have run. That will pause the current thread until the finalizer thread gets around to emptying the queue. And if you want to ensure that those finalized objects have their memory reclaimed then you're going to have to call Collect a second time.

And of course, it goes without saying that you should only be doing this for debugging and testing purposes. Never do this nonsense in production code without a really, really good reason.

这篇关于所以GC.Collect()并完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆