微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 垃圾收集应该删除对象,但WeakReference.IsAlive仍然返回true

我有一个测试,我预计通过,但垃圾收集器的行为不是我推测的:
[Test]
public void WeakReferenceTest2()
{
    var obj = new object();
    var wRef = new WeakReference(obj);

    wRef.IsAlive.Should().BeTrue(); //passes

    GC.Collect();

    wRef.IsAlive.Should().BeTrue(); //passes

    obj = null;

    GC.Collect();

    wRef.IsAlive.Should().BeFalse(); //fails
}

在这个例子中,obj对象应为GC’d,因此我希望WeakReference.IsAlive属性返回false.

看来,因为obj变量被声明在与GC.Collect相同的范围内,所以它没有被收集.如果我将对象声明和初始化移动到测试通过的方法之外.

有没有人有任何技术参考文献或解释这个行为?

解决方法

遇到同样的问题,我的测试通过无处不在,除了NCrunch之外(可能是您的情况下的任何其他工具).嗯.使用SOS进行调试会在测试方法调用堆栈上显示额外的根.我的猜测是,它们是禁用任何编译器优化的代码工具的结果,包括正确计算对象可达性的编译器优化.

这里的治疗是非常简单的 – 从来没有强调GC的方法和对活性的测试.这可以通过简单的帮助方法轻松实现.以下更改使您的测试用例与NCrunch通过,最初出现故障.

[TestMethod]
public void WeakReferenceTest2()
{
    var wRef2 = CallInItsOwnScope(() =>
    {
        var obj = new object();
        var wRef = new WeakReference(obj);

        wRef.IsAlive.Should().BeTrue(); //passes

        GC.Collect();

        wRef.IsAlive.Should().BeTrue(); //passes
        return wRef;
    });

    GC.Collect();

    wRef2.IsAlive.Should().BeFalse(); //used to fail,Now passes
}

private T CallInItsOwnScope<T>(Func<T> getter)
{
    return getter();
}

原文地址:https://www.jb51.cc/csharp/96205.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐