繁体   English   中英

Lambda闭包生命周期和计时器处理程序

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM