gpt4 book ai didi

c# - .NET 4.x : how to force full GC collection?

转载 作者:太空宇宙 更新时间:2023-11-03 10:22:30 27 4
gpt4 key购买 nike

当内置调试配置或附加调试器时,似乎有一些更新改变了 GC 行为:

//Code snippet 1
var a = new object();
var w = new WeakReference(a);
a = null;

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine(w.IsAlive ? "Alive" : "Dead");

这样的代码用来打印Dead ,并且编写单元测试非常方便,可以检查某些应该进行 GC 的部分没有被保留。

经过一些 .NET 4.x 更新后,此代码在 .NET 2.x 和 3.x 上成功通过,但在 4.x 的所有变体上均失败。我试着称它为 GC.Collect(2, GCCollectionMode.Forced, blocking: true) , 制作 <gcConcurrent enabled="false"/>App.configGCSettings.LatencyMode = GCLatencyMode.Batch - 没有任何帮助。如果我在没有附加调试器的情况下运行代码并且它是在发布配置中构建的(即优化) - 它输出 Dead .否则为 Alive .

我知道在生产中依赖 GC 并不是一个好主意。但是对于测试,我不知道如何替换通过测试检查特定代码片段不会泄漏内存的能力。它是纯测试程序集,我可以转动一些兼容性开关或类似的东西。我的目标是检查我自己的代码,而不是 GC 优化。

有没有办法以某种方式强制 GC 返回以前的行为?

附言我看到了几乎相同的 question ,不过当时跟NCrunch有关。我没有安装它。我什至从命令行运行代码,完全没有 VS,结果相同。


UPD:我发现,如果我将分配和设置 null 引用的代码移动到单独的方法中 - 它始终输出 Dead , 不过。

//Code snippet 2
internal class Program
{
private static void Main(string[] args)
{
var w = DoWorkAndGetWeakRef();

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine(w.IsAlive ? "Alive" : "Dead");
Console.ReadLine();
}

private static WeakReference DoWorkAndGetWeakRef()
{
var a = new object();
var w = new WeakReference(a);
a = null;
return w;
}
}

如果我将方法 GC 收集调用和 WeakReference 检查分开,结果相同:

//Code snippet 3
internal class Program
{
private static void Main(string[] args)
{
var a = new object();
var w = new WeakReference(a);
a = null;

CollectAndCheckWeakRef(w);
Console.ReadLine();
}

private static void CollectAndCheckWeakRef(WeakReference w1)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine(w1.IsAlive ? "Alive" : "Dead");
}
}

虽然看起来重要的一点是原始 w变量不在当前范围内。如果我移动Console.WriteLine(w1.IsAlive ? "Alive" : "Dead");返回Main - 它变成了Alive再次。

这两种变体有时不是很方便,但至少是一致的(DebugRelease 配置,是否连接调试器 - 仍然输出 Dead)。

现在我很好奇当前执行作用域中仅仅存在 WeakReference 变量是如何阻止 GC 清理其 Target 的,以及为什么将它埋在调用堆栈中的作用域中的某个地方不会做同样的事情。

最佳答案

在 Debug模式下,这应该使对象在所有 .NET 版本中保持事件状态。其他任何问题都是错误(或缺失的功能)。

您可以通过将一些代码拆分为新方法来禁用此调试帮助。

在 Release模式下,这应该表现出您想要的较短的 GC 生命周期。这当然不能保证,但这是一个非常理想的优化。

另一种解决方法是使用 new object[1] 或类似的结构。然后,您可以可靠地清空第一个数组成员。我认为该框架具有 BoxStrongBox 类型。不知道它叫什么。

关于c# - .NET 4.x : how to force full GC collection?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32876653/

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