Task.Run lambda从循环中获取错误的局部变量

时间:2017-09-19 07:44:08

标签: c# task task-parallel-library

嗨,在以下示例中,

void Main()
{
    Func<int, int> getPage = (pageNumber) =>
    {
        SimulateSlowHttpRequest();
        Console.WriteLine(pageNumber);
        return pageNumber;
    };

    var tasks = new List<Task<int>>();

    for (int i = 1; i <= 5; i++)
    {
        task = Task.Run(() => getPage(i));  
        tasks.Add(task);
    }

    Task.WaitAll(tasks.ToArray());
    //...etc
}

public static void SimulateSlowHttpRequest()
{
    var x = 1000000000;
    var multiplier = new Random().Next(8, 16);
    var y = x * multiplier;

    for (int i = 0; i <= y; i++)
    {
        var result = i++;
    }
}

我得到以下输出:

 6
 6
 6
 6
 6

..有时我可能会看到(例如)3,但大多数是6s。如果我改变这一行:

        task = Task.Run(() => getPage(i));

为:

        var j = i;
        task = Task.Run(() => getPage(j));

然后我得到预期的输出(每行数字1到5,虽然是随机顺序)。

我怀疑这是因为: a)循环中的任务可能在for循环结束后的某个未定义时间开始运行,并且 b)i通过引用传递给Func,它的最后一个值是6

我的问题是为什么它适用于上述变化(即制作i的本地副本)以及上述更好的设计?上面的代码与我正在使用的程序基本相同,该程序对REST服务进行并发调用以获取将在一个结果中返回的数据。

0 个答案:

没有答案