假设我动态创建一个这样的计时器:
System.Timers.Timer expirationTimer = new Timer(expiration * 60000);
expirationTimer.Elapsed += (sender, e) => removeExpiredCacheEntry(sessionID);
expirationTimer.Start();
当该引用超出范围时,Timer对象是否会被垃圾回收?如果是这样,活动还会开火吗?如果没有,那么在这种情况下如何避免内存泄漏?
谢谢!
答案 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;
然后“发布者”会保持“目标”活着,但“目标”不会让“发布者”保持活力。