我在类WeakReference<T>中使用Foo(short weak reference)跟踪对象。此类具有析构函数,我需要在该析构函数中访问该跟踪的对象。我跟踪的对象也使用Foo跟踪WeakReference<Foo>

所以现在我想知道WeakReference的“清零”到底何时发生?是在运行任何终结器之前,所有WeakReference都为空,还是在它们要跟踪的对象的终结器即将运行之前,它们中的每一个都为空?

更新

现在,我还想知道Mono项目是否可以对此有所启发(link 1link 2)。但是我有点担心MS GCMono GC可能以不同的方式处理此问题并且不兼容。

最佳答案

我想写一个演示这个区别的演示程序。事实证明,这比我指望的要更具挑战性。首先,必须确保终结器线程的速度可以放慢,这样您就可以观察WeakReference.IsAlive的值,而不必担心会受到终结器线程竞争的影响。所以我用了:

class FinalizerDelayer {
    ~FinalizerDelayer() {
        Console.WriteLine("Delaying finalizer...");
        System.Threading.Thread.Sleep(500);
        Console.WriteLine("Delay done");
    }
}

然后是WeakReference的目标的一个小类:
class Example {
    private int instance;
    public Example(int instance) { this.instance = instance; }
    ~Example() {
        Console.WriteLine("Example {0} finalized", instance);
    }
}

然后,一个程序演示了弱引用长和短引用之间的区别:
class Program {
    static void Main(string[] args) {
        var target1 = new Example(1);
        var target2 = new Example(2);
        var shortweak = new WeakReference(target1);
        var longweak = new WeakReference(target2, true);
        var delay = new FinalizerDelayer();
        GC.Collect();       // Kills short reference
        Console.WriteLine("Short alive = {0}", shortweak.IsAlive);
        Console.WriteLine("Long  alive = {0}", longweak.IsAlive);
        GC.WaitForPendingFinalizers();
        Console.WriteLine("Finalization done");
        GC.Collect();       // Kills long reference
        Console.WriteLine("Long  alive = {0}", longweak.IsAlive);
        Console.ReadLine();
    }
}

您必须运行此程序,以便调试器不会影响对象的生存期。选择“发布版本”并更改调试器设置:“工具+选项”,“调试”,“常规”,取消选中“抑制JIT优化”选项。

事实证明,对象的最终确定顺序确实是不确定的。每次您运行该程序的顺序都不同。我们希望FinalizerDelayer对象首先被完成,但这并不总是会发生。我认为这是内置地址空间布局随机化功能的副作用,它使托管代码很难受到攻击。但是经常运行它,您最终会得到:



长话短说:
  • 一旦收集到对象并将其放置在易碎队列中,就可以将其完成,一个简短的弱引用将IsAlive设置为false。该对象在物理上仍然存在,但是不再存在强引用,因此它将很快完成。
  • 长时间的弱引用会一直跟踪对象的真实生命周期,包括其在易碎队列中的生命。 IsAlive的终结器完成之前,不会将其设置为false。

  • 当对象恢复时要当心怪癖,当重新创建强引用时,会将对象从易碎队列移回普通堆。无需我在此演示程序中进行探索,但需要很长的弱引用才能观察到。您需要长期的薄弱引用的基本原因。

    10-04 22:24
    查看更多