如何通过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事件设置时传递实例中的值。

如何通过lambda表达式传递捕获的变量,就好像它没有被捕获一样

您正在关闭循环变量。更多信息请参阅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 "的值