0

I'm trying to spawn different threads for some processing. I use the for loop index for some logic inside each thread.
How can I get the different threads to print 1,2,3,4, 5 in the code below? Each time I run this, I get different numbers as output - 3,3,3,4,6,6 & 2,2,3,5,5,6 etc.
I tried using the lock object, but it stil wasn't doing it correctly. Can anyone help me achive this. I just want to make sure each thread/task gets the right index. Note that each task has been forced to run on a separate thread.

List<Task> tasks1 = new List<Task>();
for (int j = 1; j <= 5; j++)
{    
   tasks1.Add(Task.Factory.StartNew(() =>
          {
              Console.WriteLine(j);
          }
          , new CancellationToken()
          , TaskCreationOptions.LongRunning
          , TaskScheduler.Default)
                                   );
}

Task.WaitAll(tasks1.ToArray());
Console.Read();
4

3 回答 3

4

您正在“捕获循环变量”。在 lambda 中使用的事实j意味着编译器会以不同的方式对待它(本质上,它将被装箱)并且所有线程将使用相同的共享变量。

简短的修复:

 for (int j = 1; j <= 5; j++)
 {
     int jCopy = j;

     tasks1.Add(Task.Factory.StartNew(() =>
      {
          Console.WriteLine(jCopy);
      }, new CancellationToken(), TaskCreationOptions.LongRunning, TaskScheduler.Default)

     );
 }
于 2013-06-04T21:13:39.263 回答
3

只是为了完成其他答案。在 C# 5.0 (.NET 4.5) 中,与关闭循环变量有关的重大变化foreach,但与关闭for循环变量无关。

请参阅 Eric Lippert中的详细信息(和前言更新说明) 。关闭循环变量被认为是有害的,他的关闭循环变量,第二部分

请注意,此问题与多线程或 TPL(任务并行库)的使用无关。

其他答案和评论提到它之前已经讨论过,但没有链接到之前的任何答案。为了相互联系,这里有一些:

于 2013-06-05T02:18:08.367 回答
2

回答数百万次。它与闭包有关。更改您的代码如下

 for (int j = 1; j <= 5; j++)
 {
     int temp = j;

     tasks1.Add(Task.Factory.StartNew(() =>
      {
          Console.WriteLine(temp);
      }, new CancellationToken(), TaskCreationOptions.LongRunning, TaskScheduler.Default)

     );
 }

我建议阅读以下内容:循环变量和闭包

于 2013-06-04T21:13:00.463 回答