动态系统.定时器.定时器和垃圾收集

本文关键字:定时器 系统 动态 | 更新日期: 2023-09-27 17:53:00

假设我动态地创建一个定时器:

        System.Timers.Timer expirationTimer = new Timer(expiration * 60000);
        expirationTimer.Elapsed += (sender, e) => removeExpiredCacheEntry(sessionID);
        expirationTimer.Start();

当引用超出作用域时,Timer对象会被垃圾收集吗?如果是,事件还会触发吗?如果不是,那么在这种情况下如何避免内存泄漏?

谢谢!

动态系统.定时器.定时器和垃圾收集

根据这个答案,计时器对象确实符合垃圾收集的条件,并在某个点停止触发事件。

然而,垃圾收集被反过来阻止了。如果我们有

publisher.SomeEvent += target.SomeHandler;

那么"publisher"将使"target"保持存活,但"target"不会使"publisher"保持存活

一旦对象超出作用域,并且没有对它的额外引用。它最终会被垃圾收集起来。但这在一段时间内可能不会发生。因此,计时器可能会一直触发,直到它最终被垃圾收集。

这只是一个猜测,因为我目前没有能力测试它。

更新:

我刚刚写了一个小的测试程序,看起来像这样:

static void Main(string[] args)
{
    SetTimer();
    Console.ReadLine();
}
private static void SetTimer()
{
    Timer expirationTimer = new Timer(1000);
    expirationTimer.Elapsed += (sender, e) => Notify(e);
    expirationTimer.Start();
}
private static void Notify(ElapsedEventArgs e)
{
    Console.WriteLine(string.Format("Notified! {0}", e.SignalTime));   
}

计时器持续触发很长时间(我最终刚刚结束了程序)。有趣的是,我在main函数中插入了一个15秒的睡眠,然后调用GC.Collect(),即使在强制垃圾收集之后计时器也会继续运行,尽管不能保证调用GC.Collect()会实际做任何事情。

我还尝试在using语句中包装计时器,并且正确地立即禁用计时器(不向屏幕打印任何内容)。所以,我相信我的假设是正确的,垃圾收集将最终收集计时器,并处理它。但是没有办法确定这将是什么时候。