gpt4 book ai didi

c# - 为什么我的委托(delegate)只使用我的 foreach 循环中的最后一项?

转载 作者:太空狗 更新时间:2023-10-30 00:25:20 25 4
gpt4 key购买 nike

场景:我正在构建一个调度系统,每个计时器事件我想运行一个自定义方法而不是通常的 Timer.Elapsed 事件。

所以我写了这样的东西。

foreach (ScheduleElement schedule in schedules) {
TimeSpan timeToRun = CalculateTime(schedule);
schedule.Timer = new Timer(timeToRun.TotalMilliseconds);
schedule.Timer.Elapsed += delegate { Refresh_Timer(schedule); };
schedule.Timer.AutoReset = true;
schedule.Timer.Enabled = true;
}

好吧,非常简单,实际上确实创建了我的计时器。但是,我希望每个经过的事件都使用它传入的 schedule 元素运行。我的问题是,为什么 Elapsed 事件只在每个 Timer.Elapsed 事件的 for 循环中的最后一个 ScheduleElement 中传递。

现在我知道是什么修复了它,我只是不确定为什么。如果我回滚到原始 Timer.Elapsed 事件并使用我自己的类扩展 Timer 类,我可以解决它。就像这样。

修复:

foreach (ScheduleElement schedule in schedules) {
TimeSpan timeToRun = CalculateTime(schedule);
schedule.Timer = new TimerEx(timeToRun.TotalMilliseconds);
schedule.Timer.Elapsed +=new System.Timers.ElapsedEventHandler(Refresh_Timer);
schedule.Timer.Tag = schedule;
schedule.Timer.AutoReset = true;
schedule.Timer.Enabled = true;
}

然后我将 object sender 转换回其原始对象,并窃取它的 Tag 属性,这为我提供了每个唯一计时器的正确时间表。

那么,为什么使用 delegate { } 只在所有 Timer 的 foreach 循环中传入最后一个 ScheduleElement

编辑 1

定时器类

public TimerEx : Timer {

public TimerEx(double interval) : base(interval) { }

private Object _Tag;

public Object Tag {
get { return _Tag; }
set { _Tag = value; }
}
}

最佳答案

这是因为您在委托(delegate)中使用了闭包,它关闭了同一个变量,该变量在 foreach 循环的每次迭代中共享。

有关详细信息,请参阅 Eric Lippert 的文章 Closing over the loop variable considered harmful .

在这种情况下,您可以使用临时方法轻松修复它:

foreach (ScheduleElement schedule in schedules) {
TimeSpan timeToRun = CalculateTime(schedule);
schedule.Timer = new Timer(timeToRun.TotalMilliseconds);

// Make a temporary variable in the proper scope, and close over it instead
var temp = schedule;
schedule.Timer.Elapsed += delegate { Refresh_Timer(temp); };

请注意,C# 5 更改了 foreach 循环的这种行为。如果您使用最新的编译器编译它,问题将不再存在。

关于c# - 为什么我的委托(delegate)只使用我的 foreach 循环中的最后一项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17688790/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com