[英]Lambda closure lifetime and timer handlers
我通常避免使用局部变量来保存对计时器的引用,因为当局部变量超出范围时,计时器会被垃圾收集并停止触发。 但是,我遇到了一些似乎通过附加到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();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.