如何通过lambda表达式传递捕获的变量,就好像它没有被捕获一样
本文关键字:一样 表达式 lambda 何通过 变量 | 更新日期: 2023-09-27 18:16:14
我想要一段测试代码,它创建一个任务集合,然后在不久的将来随机调用每个任务索引的方法。
我是这样写的:
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的博客文章。
基本上,延迟执行是使用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();
}
我在这里只是猜测(没有真正测试过),如果你在for循环代码中分配一个局部值,应该捕获迭代的值。
Random rnd = new Random();
for (Int32 taskIdx = 0; taskIdx < 10; taskIdx++)
{
var taskIndex = taskIdx;
_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();
}
通常这样做是为了捕获" This "的值