代码之家  ›  专栏  ›  技术社区  ›  Ian Ringrose

在完全垃圾收集之后,WeakReference.IsLive()变为false之前是否有延迟?

  •  2
  • Ian Ringrose  · 技术社区  · 14 年前

    我已经编写了一个单元测试来确认类上的Dispose是否会取消所有事件的锁定,并处理引用该对象的计时器。

    然而 有时 WeakReference.IsLive()在我希望它返回false时返回true?

    那么,在更新WeakReference.IsLive()之前,完整GC之后是否有延迟?

    如果不是的话,你能想出其他什么能给我带来不可重复的结果吗?

    WeakReference weekJobWatchDog = new WeakReference(jobWatchDog);
    jobWatchDog = null;
    
    // not collected before Dispose called due to timer and events etc
    GC.Collect(); GC.Collect();
    Assert.IsTrue(weekJobWatchDog.IsAlive);
    
    ((IDisposable)weekJobWatchDog.Target).Dispose();
    
    // is now collected as Dispose unlocked all events and dispoed the timer
    GC.Collect(); GC.Collect();
    Assert.IsFalse(weekJobWatchDog.IsAlive); // sometimes this fails, about 1 in 4 runs
    

    另见 Testing Finalizers and IDisposable 为了一个相关但不同的问题。

    How can I write a unit test to determine whether an object can be garbage collected? 有一个包含调用GC.WaitForPendingFinalizers()的解决方案,但是我不想调用GC.WaitForPendingFinalizers(),因为我希望证明我的dispose工作正常,如果工作正常,则不需要运行任何终结器。

    3 回复  |  直到 8 年前
        1
  •  0
  •   LukeH    14 年前

    自从 Collect 方法没有阻塞,那么我猜——这只是猜测——GC在您测试时没有收集对象 IsAlive .

    (别忘了 you can only trust IsAlive when it returns false .)

    我想解决方法可能是对类似 WaitForPendingFinalizers ,即使您没有自己的终结器等待。(我不确定是否有其他合适的阻塞方法可以替代。)

        2
  •  0
  •   Community CDub    8 年前

    这就是问题所在 有:

    当对System.Timers.Timer调用Dispose()时 可以 在Win32计时器被销毁之前返回。因此,在非托管空间中仍有一个根目录保持计时器活动。时间有一个事件处理程序,它使我的对象保持活动状态。

    由于这是非常及时的相关,大部分时间计时器将得到GCed和我的对象。但是有时(比如说10次中的1次)计时器会保持活动状态,我的对象也会保持活动状态。

    短时间的睡眠()会使我的测试100%通过,所以在处理事件之前取消计时器上的挂钩,这样计时器就无法使我的对象保持活动状态。

    另见 How do I safely dispose a System.Timers.Timer?

        3
  •  -2
  •   supercat    14 年前

    如果WeakReference的IsLive属性返回false,则表示该引用是kaput,并且将永远是kaput,无需检查其值。如果返回true,则表示引用 可以 活着,但除非你试图把它的价值转化为一个有力的参考,否则你不会真正知道。一个人不应该依赖于一个特定程度的及时性而无效的会议,也不应该接受它的价值,除非你真的对它感兴趣。如果您正在执行诸如清理WeakReferences列表、删除已死亡的WeakReferences之类的操作,则IsAlive属性允许您标识已完全死亡的WeakReferences,而不创建对那些可能符合垃圾收集条件的WeakReferences的强引用。对于列表中的任何弱引用何时有资格进行清理,没有特别的保证,但是(1)在存在内存压力的情况下,这样的资格将更及时;(2)在没有内存压力的情况下,时间性通常不会成为问题。