簡體   English   中英

對象GC之后,C#弱引用仍然有效嗎?

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

我有一個快速的代碼段可以測試弱引用,我希望在對象成為GC之后,弱引用應該不再返回對象引用。 但是我的測試表明這不是預期的:

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.
    }
}

它打印:

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

我在哪里弄錯了?

謝謝。

當您在一個弱引用上調用TryGetTarget時,假設尚未收集被引用的對象,您將獲得對該對象的強引用。 您在代碼中執行了3次: p1p2p3是對該對象的強引用。 當垃圾收集器運行時-自動運行或在您強制垃圾收集時運行-那些強引用將阻止對象的收集。

這是一個有效的版本:

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;
}

請注意,在任何情況下,我們始終都不會對對象保持強大的引用超過幾個周期,並且在垃圾回收器運行時,沒有針對該對象的強大引用,因此無法收集該對象。

即使在這段代碼中,即使我注釋掉p = null; 行中的垃圾收集器可能不會收集對象。 試試看。

這個故事的寓意是:當您從WeakReference<>獲得強引用時,在完成該操作后, 始終將其WeakReference<>空。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM