首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >强制WeakReference的目标被垃圾收集

强制WeakReference的目标被垃圾收集
EN

Stack Overflow用户
提问于 2021-06-22 07:42:24
回答 1查看 141关注 0票数 2

在我的程序中,我有一个服务对象,它保持对对象的弱引用。我有一个自动测试,它断言当所有对对象的引用被删除时,弱引用就会被释放。测试的目的是证明当对象没有理由被保存在内存中时,服务不会导致对象留在内存中。

下面是该测试的简化版本:

代码语言:javascript
复制
[Test]
public void WeakReference()
{
    var o = Allocate();
    var reference = new WeakReference(o.Value);
    Assert.IsTrue(reference.IsAlive);

    o.Value = null;
    GC.Collect();
    Assert.IsFalse(reference.IsAlive);
}

private MyObject Allocate()
{
    return new MyObject
    {
        Value = new object()
    };
}

private class MyObject
{
    public object Value { get; set; }
}

在.NET 4.8 NUnit测试项目中,此测试通过。但是,在项目的当前分支中,我在.NET 5项目中进行了测试。在该项目中,由于弱引用保持“活动”,相同的测试代码会失败。

我还尝试将GC.Collect()调用更改为

代码语言:javascript
复制
GC.Collect(int.MaxValue, GCCollectionMode.Forced, blocking: true);

没有骰子。

在.NET 5中垃圾收集的工作方式是否发生了根本性的变化,使上述代码不再工作?如何才能仍然证明我的服务对象没有保存在内存中的对象?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-18 17:10:30

在以下三种情况下,我能够让你的考试通过:

IsAlive.

  • Compiler优化是ON.

  • The调试器的
  1. 循环是而不是附加的。

此修改后的测试代码演示了上面第1段中提到的循环,并多次重复测试。对我来说总是如此。

代码语言:javascript
复制
[Test, Repeat(1000)]
public void WeakReference()
{
    var o = Allocate();
    var reference = new WeakReference(o.Value);
    Assert.IsTrue(reference.IsAlive);

    o.Value = null;

    for (var i = 0; i < 2 && reference.IsAlive; i++)
        GC.Collect();

    Assert.IsFalse(reference.IsAlive);
}

我还没有足够的知识来解释为什么会这样做,但我已经发现,这与导致对象引用成为GC根的条件有关(始终是可访问的,而不是GC可收集的)。

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

https://stackoverflow.com/questions/68079430

复制
相关文章

相似问题

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