gpt4 book ai didi

c# - 使用 GC.Collect() 是正确的; GC.WaitForPendingFinalizers();?

转载 作者:IT王子 更新时间:2023-10-29 04:11:01 25 4
gpt4 key购买 nike

我开始审查项目中的一些代码并发现了类似这样的内容:

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

这些线条通常出现在旨在提高效率的理由下破坏对象的方法上。我发表了以下评论:

  1. 在销毁每个对象时显式调用垃圾回收会降低性能,因为这样做没有考虑到 CLR 性能是否绝对必要。
  2. 按此顺序调用这些指令会导致每个对象仅在其他对象正在完成时才被销毁。因此,一个可以独立销毁的对象必须在没有真正必要的情况下等待另一个对象的销毁。
  3. 它会产生死锁(参见:this question)

1、2 和 3 是真的吗?你能提供一些引用来支持你的答案吗?

虽然我几乎可以肯定我的言论,但我需要在我的论点中说清楚,以便向我的团队解释为什么这是一个问题。这就是我要求确认和引用的原因。

最佳答案

简短的回答是:把它拿出来。该代码几乎永远不会提高性能或长期内存使用。

你所有的观点都是正确的。 (它可以产生死锁;这并不意味着它总是。)调用GC.Collect()将收集所有GC的内存几代人。这有两个作用。

  • 每次 都收集所有代 - 而不是 GC 默认情况下执行的操作,即仅在代已满时收集。在典型的使用中,Gen0 的收集频率(大约)是 Gen1 的十倍,而 Gen1 的收集频率(大约)是 Gen2 的十倍。此代码每次都会收集所有世代。 Gen0 收集通常低于 100 毫秒; Gen2 可以更长。
  • 它将不可收集的对象提升到下一代。也就是说,每次你强制收集并且你仍然有对某个对象的引用时,该对象将被提升到后续生成。通常这种情况很少发生,但是如下代码会更频繁地强制发生这种情况:

    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 将在 Gen1 中结束 - 这意味着自动 Gen0 集合不会释放该内存。

还值得注意的是一个更大的恐怖:在 DEBUG 模式下,GC 的功能不同并且不会回收仍在范围内的任何变量(即使它以后没有在当前方法中使用)。所以在 DEBUG 模式下,上面的代码在调用 GC.Collect 时甚至不会收集 o1,所以 o1o2 将被提升。在调试代码时,这可能会导致一些非常不稳定和意外的内存使用。 (this 等文章强调了这种行为。)

编辑:刚刚测试了这种行为,有些讽刺意味:如果你有这样的方法:

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

... 然后它会显式地不释放 someObject 的内存,即使在 RELEASE 模式下:它会将它提升到下一代 GC。

关于c# - 使用 GC.Collect() 是正确的; GC.WaitForPendingFinalizers();?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12265598/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com