【发布时间】:2010-04-06 10:10:25
【问题描述】:
我刚刚使用扩展方法回答了quite simple question。但写下来后,我记得你不能从事件处理程序中取消订阅 lambda。
到目前为止没有什么大问题。但是这一切在扩展方法中是如何表现的呢?
下面是我的代码再次被剪断。那么,如果您多次调用此扩展方法,是否会导致无数计时器在内存中徘徊?
我会说不,因为计时器的范围被限制在这个函数中。所以离开它之后,没有其他人可以引用这个对象。我只是有点不确定,因为我们在静态类的静态函数中。
public static class LabelExtensions
{
public static Label BlinkText(this Label label, int duration)
{
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = duration;
timer.Tick += (sender, e) =>
{
timer.Stop();
label.Font = new Font(label.Font, label.Font.Style ^ FontStyle.Bold);
};
label.Font = new Font(label.Font, label.Font.Style | FontStyle.Bold);
timer.Start();
return label;
}
}
更新
只是为了澄清我使用了System.Windows.Forms.Timer。因此,从您的回答看来,尤其是使用这个计时器类是正确的选择,因为在这种情况下,它会按照我所期望的方式执行任何操作。如果您在这种情况下尝试另一个计时器类,您可能会遇到Matthew found out 的麻烦。 如果我的对象是否还活着,我也可以使用 WeakReferences found a way。
更新 2
经过一点睡眠和更多思考后,我还对我的测试仪(answer below)进行了另一项更改,我只是在最后一行之后添加了一个GC.Collect(),并将持续时间设置为 10000。在启动 BlinkText() 之后有几次我一直按我的 button2 来获取当前状态并强制进行垃圾收集。而且看起来所有的计时器都将在调用Stop() 方法之后被销毁。因此,当我的 BlinkText 已经离开并且计时器正在运行时,垃圾收集也不会导致任何问题。
因此,在您的所有良好响应和更多测试之后,我可以很高兴地说,它只是做了它应该做的事情,而不会将计时器留在内存中,也不会在计时器完成工作之前将其丢弃。
【问题讨论】:
-
你的代码会因为非法的跨线程调用而失败。您的计时器(特别是 Winforms 计时器)需要有一个同步对象。
-
@leppie:错了,这个 Timer 正在使用 messagepump。试试看。
-
@Henk Holterman:谢谢,看来我把它和
System.Timers.Timer混淆了。
标签: c# lambda extension-methods