为什么任务列表导致错误结果。 任何人都可以给出指示?
到目前为止我的代码。
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
提前致谢。
答案 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
次迭代都会获得变量的新副本。