我想要一段测试代码,它创建任务集合,然后在不久的将来的某个随机时间调用每个任务索引的方法。
我是这样写的:
Random rnd = new Random();
for (Int32 taskIndex = 0; taskIndex < 10; taskIndex++)
{
_tasks.Add(String.Format("Task_{0}", taskIndex));
Progress.AddItem(_tasks[taskIndex]);
Int32 timeDelay = 5 + rnd.Next(10);
DispatcherTimer dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Interval = TimeSpan.FromSeconds(timeDelay);
dispatcherTimer.Tick += (sndr, eArgs) =>
{
dispatcherTimer.Stop();
Progress.SetItemStatus(taskIndex, Status.Executing);
};
dispatcherTimer.Start();
}
当它运行时,它总是将 10 作为任务索引传递给 Progress.SetItemStatus()。我明白为什么会这样(谢谢,Skeet 先生) - 因为 taskIndex 是在匿名方法中捕获的,并在执行方法时使用它的值。
我想知道的是实现我的目标的最优雅的方法,即在设置 Tick 事件时传递实例中的值。
最佳答案
您正在关闭循环变量。请参阅Eric Lippert’s Blog发帖获取更多信息。
基本上,延迟执行使用的是taskIndex,它在执行时将始终为10(或最后一个值)。
Random rnd = new Random();
for (Int32 taskIndex = 0; taskIndex < 10; taskIndex++)
{
Int32 tempIndex = taskIndex;
_tasks.Add(String.Format("Task_{0}", tempIndex));
Progress.AddItem(_tasks[tempIndex]);
Int32 timeDelay = 5 + rnd.Next(10);
DispatcherTimer dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Interval = TimeSpan.FromSeconds(timeDelay);
dispatcherTimer.Tick += (sndr, eArgs) =>
{
dispatcherTimer.Stop();
Progress.SetItemStatus(tempIndex, Status.Executing);
};
dispatcherTimer.Start();
}
关于c# - 如何通过 lambda 表达式传递捕获的变量,就好像它未被捕获一样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16864406/