简体   繁体   English

对象GC之后,C#弱引用仍然有效吗?

[英]C# weak reference still valid after object GC?

I've got a quick code piece to test weak reference, I expect that after the object being GC, the weak reference should not longer return a object referenct. 我有一个快速的代码段可以测试弱引用,我希望在对象成为GC之后,弱引用应该不再返回对象引用。 But my test shows this is not expected: 但是我的测试表明这不是预期的:

class Person
{
    private int mI = 3;
    public int MI { get => mI; set => mI = value; }
}
class UseWeakReference
{
    public static void Main(String[] args)
    {
        Person person = new Person();
        WeakReference<Person> wr = new WeakReference<Person>(person);

        wr.TryGetTarget(out Person p1);
        Console.WriteLine(p1);

        person = null;
        wr.TryGetTarget(out Person p2);
        Console.WriteLine(p2);

        p2 = null;
        System.GC.Collect();
        Thread.Sleep(1000);
        wr.TryGetTarget(out Person p3);
        Console.WriteLine(p3); // I expected null here becaure person is collected.
    }
}

It prints: 它打印:

MyApp1.Person
MyApp1.Person
MyApp1.Person // Why still valid?

Where did I get wrong? 我在哪里弄错了?

Thanks. 谢谢。

When you call TryGetTarget on a weak reference, assuming that the referenced object has not already been collected, you get back a strong reference to that object. 当您在一个弱引用上调用TryGetTarget时,假设尚未收集被引用的对象,您将获得对该对象的强引用。 You do this 3 times in your code: p1 , p2 and p3 are strong references to the object. 您在代码中执行了3次: p1p2p3是对该对象的强引用。 When the garbage collector runs - automatically or in your case when you force garbage collection - those strong references will prevent the object being collected. 当垃圾收集器运行时-自动运行或在您强制垃圾收集时运行-那些强引用将阻止对象的收集。

Here's a version that works: 这是一个有效的版本:

void Main()
{
    var person = new Person();
    WeakReference<Person> weak = new WeakReference<Person>(person);
    person = null;

    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine($"{i}\t{TestReference(weak)}");
        Thread.Sleep(100);
    }

    GC.Collect();
    Console.WriteLine(TestReference(weak));
}

class Person
{
    private int mI = 3;
    public int MI { get => mI; set => mI = value; }
}

bool TestReference(WeakReference<Person> weak)
{
    if (weak.TryGetTarget(out Person p))
    {
        p = null;
        return true;
    }
    return false;
}

Note that at no point are we keeping a strong reference to the object alive for more than a few cycles, and by the time the garbage collector runs there are no strong references to the object so the object is collected. 请注意,在任何情况下,我们始终都不会对对象保持强大的引用超过几个周期,并且在垃圾回收器运行时,没有针对该对象的强大引用,因此无法收集该对象。

Even in this code though if I comment out the p = null; 即使在这段代码中,即使我注释掉p = null; line the garbage collector may not collect the object. 行中的垃圾收集器可能不会收集对象。 Try it and see. 试试看。

The moral of the story is: when you obtain a strong reference from a WeakReference<> , always null the strong reference when you're done with it. 这个故事的寓意是:当您从WeakReference<>获得强引用时,在完成该操作后, 始终将其WeakReference<>空。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM