正确使用GC.Collect的(); GC.WaitForPendingFinalizers();? [英] Is correct to use GC.Collect(); GC.WaitForPendingFinalizers();?

查看:1477
本文介绍了正确使用GC.Collect的(); GC.WaitForPendingFinalizers();?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始复习一下code在一个项目中,发现这样的:

I've started to review some code in a project and found something like this:

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

这些行通常出现在被设想为销毁的提高效率的基本原理下的对象的方法。我做了这样的言论:

Those lines usually appear on methods that are conceived to destruct the object under the rationale of increase efficiency. I've made this remarks:

  1. 要显式调用垃圾收集中的每个对象的破坏降低性能,因为这样做有没有考虑到,如果它是CLR性能绝对有必要的。
  2. 在调用的顺序这些指令会导致他们只能在其他物体正在最后定稿,被销毁的每个对象。因此,一个对象可能被独立地破坏必须等待其它物体的破坏没有一个真正的必要性。
  3. 它可以产生死锁(参见:<一href="http://stackoverflow.com/questions/4386585/can-you-deadlock-on-calling-gc-collect-and-gc-waitforpendingfinalizers">this问题)

1,2和3是真的吗?您能否给一些参考支持你的答案?

Are 1, 2 and 3 true? Can you give some reference supporting your answers?

虽然我几乎可以肯定我的话,我需要清楚我的观点,以解释我的球队为什么这是一个问题。这就是我所要求的确认和参考的原因。

Although I'm almost sure about my remarks, I need to be clear in my arguments in order to explain to my team why is this a problem . That's the reason I'm asking for confirmation and reference.

推荐答案

简短的回答是:把它拿出来。这code也就差不多的永远的提高性能,或长期的内存使用。

The short answer is: take it out. That code will almost never improve performance, or long-term memory use.

所有你的观点是正确的。 (它的可以的产生死锁。这并不意味着它永远的将会的)呼叫 GC.Collect的()将收集所有GC几代人的记忆。这做了两件事。

All your points are true. (It can generate a deadlock; that does not mean it always will.) Calling GC.Collect() will collect the memory of all GC generations. This does two things.

  • 在它收集所有世代的每次的 - 而不是什么GC将默认情况下做的,这是只收集了一代时已满。典型的使用将会看到Gen0收集(大约)的十倍往往比的Gen1,这反过来又收集(大约)10倍尽可能经常的Gen2。这code每次都将收集所有代。 Gen0集合是典型的子100ms的;第二代可以更长。
  • 有促进非收藏对象到下一代。也就是说,每次强制集合,你仍然有参考一些对象,该对象将被提升到后代。通常情况下会出现这种情况相对较少,但code,如将在下面更经常迫使这样的:

  • It collects across all generations every time - instead of what the GC will do by default, which is to only collect a generation when it is full. Typical use will see Gen0 collecting (roughly) ten times as often than Gen1, which in turn collects (roughly) ten times as often as Gen2. This code will collect all generations every time. Gen0 collection is typically sub-100ms; Gen2 can be much longer.
  • It promotes non-collectable objects to the next generation. That is, every time you force a collection and you still have a reference to some object, that object will be promoted to the subsequent generation. Typically this will happen relatively rarely, but code such as the below will force this far more often:

void SomeMethod()
{ 
 object o1 = new Object();
 object o2 = new Object();

 o1.ToString();
 GC.Collect(); // this forces o2 into Gen1, because it's still referenced
 o2.ToString();
}

如果没有一个 GC.Collect的(),这两个项目将在下次有机会收集。 的集合作为软件写, O2 将结束在第一代 - 这意味着自动化的Gen0收集的不会的释放该内存。

Without a GC.Collect(), both of these items will be collected at the next opportunity. With the collection as writte, o2 will end up in Gen1 - which means an automated Gen0 collection won't release that memory.

另外值得一提的一个更大的恐怖:在调试模式下,GC的功能不同,将不会收回仍然在范围内的任何变量(即使它后来在当前方法不使用)。因此,在调试模式下,code以上甚至不收取 01 打电话时 GC.Collect的,和所以无论 01 O2 将得到提升。调试code时,这可能会导致一些非常古怪和意外的内存使用情况。 (文章如强调这种行为。)

It's also worth noting an even bigger horror: in DEBUG mode, the GC functions differently and won't reclaim any variable that is still in scope (even if it's not used later in the current method). So in DEBUG mode, the code above wouldn't even collect o1 when calling GC.Collect, and so both o1 and o2 will be promoted. This could lead to some very erratic and unexpected memory usage when debugging code. (Articles such as this highlight this behaviour.)

编辑:虽只是测试这种行为,一些真正具有讽刺意味的​​:如果你有一个方法是这样的:

Having just tested this behaviour, some real irony: if you have a method something like this:

void CleanUp(Thing someObject)
{
    someObject.TidyUp();
    someObject = null;
    GC.Collect();
    GC.WaitForPendingFinalizers(); 
}

......然后它会明确规定不释放someObject的内存,即使在发布模式:它会推动它进入下一个GC一代

... then it will explicitly NOT release the memory of someObject, even in RELEASE mode: it'll promote it into the next GC generation.

这篇关于正确使用GC.Collect的(); GC.WaitForPendingFinalizers();?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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