2014-01-22 77 views
0

为什么导致错误结果的任务列表。 任何人都可以给方向?并行任务导致错误结果

这是我的代码到目前为止。

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; 
     } 

我期望导致这样的:

测试一个 试验B 试验C 测试d 测试电子邮件 测试f

但是我上面的代码得到的是这样的: 测试f test f test f test f test f test f

在此先感谢。

回答

2

这条线是罪魁祸首:

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

Lambda表达式,其捕获的str变量,在运行任务时仅进行评价。

在这种情况下,任务的线程在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迭代现在得到的变量的新副本。

+0

感谢@dcastro您的指导和解释:) –