动态System.Timers.Timer和垃圾收集?

时间:2011-04-22 21:52:01

标签: c# .net

假设我动态创建一个这样的计时器:

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

当该引用超出范围时,Timer对象是否会被垃圾回收?如果是这样,活动还会开火吗?如果没有,那么在这种情况下如何避免内存泄漏?

谢谢!

2 个答案:

答案 0 :(得分:2)

一旦对象超出范围,就没有对它的额外引用。它最终将被垃圾收集。但这可能不会发生一段时间。因此,计时器可能会继续发射,直到它最终被垃圾收集。

这只是一个猜测,因为我现在没有能力进行测试。

更新:

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

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语句中,并且正确地立即禁用了计时器(没有在屏幕上打印任何内容)。所以,我相信我的假设是正确的,垃圾收集最终将收集计时器,并处理它。但是没有办法确定何时会这样。

答案 1 :(得分:2)

根据this answer,计时器对象确实有资格进行垃圾收集,并且在某些时候停止触发事件。

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

publisher.SomeEvent += target.SomeHandler;

然后“发布者”会保持“目标”活着,但“目标”不会让“发布者”保持活力。