将int变量传递给任务时,我经常得到奇怪的结果:例如:
List<List<object>> ListToProcess = new List<List<object>>();
// place some lists in list to process
foreach (var temp in Foo)
ListToProcess.Add(temp);
foreach (var tempArray in ListToProcess)
{
// initialize each list in ListToProcess
}
int numberOfChunks = ListToProcess.Count;
Task[] tasks = new Task[numberOfChunks];
for (int counter = 0; counter < numberOfChunks; counter++)
{
tasks[counter] = Task.Factory.StartNew(() =>
{
// counter is always = 5 why? <---------------------------
var t = ListToProcess[counter];
});
}
我该如何解决这个问题?
答案 0 :(得分:3)
这被称为闭包。您没有使用变量的值,您正在使用变量本身。代码执行时,它使用执行时的值,而不是定义任务时的值。
要解决这个问题,我相信你会做这样的事情:
for (int counter = 0; counter < numberOfChunks; counter++)
{
int cur = counter;
tasks[counter] = Task.Factory.StartNew(() =>
{
// counter is always = 5 why? <---------------------------
var t = ListToProcess[cur];
});
}
答案 1 :(得分:1)
无法保证何时访问StartNew的Action块中的'counter'变量。可能发生的是,循环所有5个值,并创建任务,然后安排任务运行。
当它们运行时,执行以下操作:
var t = ListToProcess[counter];
但在这个阶段,计数已经等于5。
也许您应该看看并行集合?
ListToProcess.AsParallel().ForAll(list => dosomething(list));
该地区还有很多其他选择。
答案 2 :(得分:0)
for (int counter = 0; counter < numberOfChunks; counter++)
{
var referenceVariable = new{val=counter};
tasks[counter] = Task.Factory.StartNew(() =>
{
var t = ListToProcess[referenceVariable.val];
});
}
答案 3 :(得分:0)
由于捕获了变量,您可以通过在每个循环中重新声明一个新变量来解决此问题。
for (int counter = 0; counter < numberOfChunks; counter++)
{
int localCounter = counter;
tasks[localCounter] = Task.Factory.StartNew(() =>
{
// counter is always = 5 why? <---------------------------
var t = ListToProcess[localCounter];
});
}