Lambda闭包生命周期和计时器处理程序
本文关键字:计时器 处理 程序 周期 闭包 生命 Lambda | 更新日期: 2023-09-27 18:16:30
我通常避免使用局部变量来保存对计时器的引用,因为当局部变量超出作用域时,计时器会被垃圾收集并停止触发。但是,我遇到了一些代码,似乎通过附加到Elapsed
事件的lambda表达式中的闭包引用计时器本身来解决这个问题。
{
var bkgTimer = new System.Timers.Timer(timeDelay) {AutoReset = false};
bkgTimer.Elapsed += (sender, args) => Handler(e, bkgTimer);
bkgTimer.Start();
}
然后,在Handler中:
private void Handler( ... timer)
{
...
timer.Dispose();
}
它似乎有效。这种方法有什么问题吗?我想知道它是否会导致内存泄漏,因为我不明白lambda闭包的生命周期是由。
对象不能仅仅通过引用自身来避免GC—这是真正的垃圾收集器和引用计数技术之间的关键区别。如果GC不能从根到达它,它将收集它。
调用GCHandle.Alloc
防止收集,调用Handler
方法中的GCHandle.Free
防止泄漏。
文档中使用GC.KeepAlive
的建议只适用于长时间运行的方法。如果该方法立即退出,就像您的方法那样,那么GC.KeepAlive
将无法达到预期的效果。
var bkgTimer = new System.Timers.Timer(timeDelay) {AutoReset = false};
var timerHandle = GCHandle.Alloc(bkgTimer);
bkgTimer.Elapsed += (sender, args) => {
…
timerHandle.Free();
bkgTimer.Dispose();
};
bkgTimer.Start();