Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程重入问题_C#_Multithreading_Loops_Closures_Task Parallel Library - Fatal编程技术网

C# 多线程重入问题

C# 多线程重入问题,c#,multithreading,loops,closures,task-parallel-library,C#,Multithreading,Loops,Closures,Task Parallel Library,我正在尝试为一些处理生成不同的线程。我对每个线程内的一些逻辑使用for循环索引。 如何让不同的线程在下面的代码中打印1,2,3,4,5?每次运行此程序时,我都会得到不同的数字作为输出—3、3、3、4、6、6和2、2、3、5、5、6等。 我试着使用lock对象,但它仍然没有正确使用。有人能帮我做到这一点吗。我只是想确保每个线程/任务都有正确的索引。请注意,每个任务都被强制在单独的线程上运行 List<Task> tasks1 = new List<Task>(); for

我正在尝试为一些处理生成不同的线程。我对每个线程内的一些逻辑使用
for
循环索引。
如何让不同的线程在下面的代码中打印1,2,3,4,5?每次运行此程序时,我都会得到不同的数字作为输出—3、3、3、4、6、6和2、2、3、5、5、6等。
我试着使用lock对象,但它仍然没有正确使用。有人能帮我做到这一点吗。我只是想确保每个线程/任务都有正确的索引。请注意,每个任务都被强制在单独的线程上运行

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();
List tasks1=新列表();
对于(int j=1;j
{
控制台写入线(j);
}
,新的CancellationToken()
,TaskCreationOptions.LongRunning
,TaskScheduler.Default)
);
}
Task.WaitAll(tasks1.ToArray());
Console.Read();

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

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

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

     );
 }
for(int j=1;j
{
控制台写入线(临时);
},new CancellationToken(),TaskCreationOptions.LongRunning,TaskScheduler.Default)
);
}

我建议您阅读以下内容:

您正在“捕获循环变量”。在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)

     );
 }
for(int j=1;j
{
Console.WriteLine(jCopy);
},new CancellationToken(),TaskCreationOptions.LongRunning,TaskScheduler.Default)
);
}

只需完成其他答案。在C#5.0(.NET 4.5)中,与每个循环变量的关闭时间相关,但与循环变量的关闭时间相关,出现了突破性变化

请参阅Eric和他的文章中的详细信息(和前言更新说明)

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

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

  • 等等

+1表示“回答了数百万次”。堆栈溢出已成为此类问题的垃圾堆。显然,这是一个混乱的根源,他们在3.0中更改了它。对不起,我问了这个问题。@AlexJ我希望你的意思是
foreach
而不是
for
(在c#5.0而不是3.0中)你说的是短修复,还有其他的吗?这里没有拳击。该变量由lambda捕获,但它被捕获为
int
变量,而不是
对象
变量。给未来的寻求答案者一个提示:这个问题与多线程或TPL(任务并行库)的使用无关
任务创建选项的正确使用。LongRunning
5
Console.WriteLine()的循环很难长时间运行