并行任务导致错误的结果

时间:2014-01-22 10:07:56

标签: c# parallel-processing

为什么任务列表导致错误结果。 任何人都可以给出指示?

到目前为止我的代码。

static string[] kk = new string[] { "a", "b", "c", "d", "e", "f" };

static void Main(string[] args)
    {
        //Parallel.For(0, 10, i => Test(i));
        //Console.ReadLine();

        foreach(string str in kk)
        {
            Task<string> task = Task.Factory.StartNew(() => Test(str));
            listTask.Add(task);
        }

        do
        {
            Thread.Sleep(100);
        }while(!Task.WaitAll(listTask.ToArray(),1000));

        foreach (Task<string> task in listTask)
        {
            Console.WriteLine(task.Status.ToString() + " : " + task.Result);
        }

        Console.ReadLine();
    }

 private static string Test(string i)
        {
             return "test " + i;
        }

我期待这样的结果:

测试a 测试b 测试c 测试d 测试e 测试f

但我上面的代码结果是这样的: 测试f 测试f 测试f 测试f 测试f 测试f

提前致谢。

1 个答案:

答案 0 :(得分:2)

这条线是罪魁祸首:

Task<string> task = Task.Factory.StartNew(() => Test(str));

捕获str变量的lambda表达式仅在运行任务时进行评估。

在这种情况下,一旦foreach循环结束,任务的线程就被激活了 - 这意味着Test(str)将被评估为所有六个调用的Test("f")。发生这种情况是因为foreach实现为所有迭代重用str变量,因此所有六个lambda表达式都捕获了相同的变量。

尝试将其更改为:

var localStr = str;
Task<string> task = Task.Factory.StartNew(() => Test(localStr));

这将使每个表达式捕获它自己的局部变量。

修改

此问题已在C#5中修复:Has foreach's use of variables been changed in C# 5?

每次foreach次迭代都会获得变量的新副本。