2012-04-11 57 views
0

我路过INT变量任务时经常会奇怪resulst如下面的例子:传递非参考价值任务

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

我怎样才能解决这个问题?

+2

闭包捕获变量,而不是值。 请参阅http://stackoverflow.com/questions/271440/c-sharp-captured-variable-in-loop – 2012-04-11 23:00:00

回答

2

这被称为闭包。你没有使用变量的值,你正在使用变量本身。代码执行时,它会在执行时使用该值,而不是定义任务时的值。

要解决这个问题,我相信你会做这样的事情:

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

无法保证何时访问StartNew的Action块中的'counter'变量。可能发生的情况是所有5个值都循环遍历,并且创建任务,然后计划任务运行。

当他们运行,以下规则执行:

var t = ListToProcess[counter]; 

但现阶段数已经等于5

也许你应该看看并行收集?

ListToProcess.AsParallel().ForAll(list => dosomething(list)); 

这个地区有很多其他的选择。

0
for (int counter = 0; counter < numberOfChunks; counter++) 
    { 
     var referenceVariable = new{val=counter}; 
     tasks[counter] = Task.Factory.StartNew(() => 
      { 
       var t = ListToProcess[referenceVariable.val];       
      }); 
    } 
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];       
     }); 
}