C#中的线程:如何保持循环索引线程安全?

在下面的示例中,似乎for循环的索引i由每个线程独立修改,导致DoWork_Threaded()i奇怪值(倍数,甚至大于System.Environment.ProcessorCount-1DoWork_Threaded()

如何在C#中正确完成multithreading循环?

 // Prepare all threads Thread[] threads = new Thread[System.Environment.ProcessorCount]; // Start all threads for (int i = 0; i  DoWork_Threaded(i)); threads[i].Start(); } // Wait for completion of all threads for (int i = 0; i < System.Environment.ProcessorCount; i++) { threads[i].Join(); } 

首先,为什么不使用任务并行库而不是滚动自己的线程调度服务? 它已经具有确定调度线程的处理器数量的逻辑。

要回答您的实际问题,您将关闭循环变量 。 看我的文章为什么那是错的:

https://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/

简而言之: i是一个变量 ,变量也在变化 。 当lambda执行时,它将以i当前值执行,而不是在创建委托时使用的值。

使用具有匿名方法和线程的局部变量可能会很棘手。 您需要复制匿名方法在更改时使用的值:

 for (int i = 0; i < System.Environment.ProcessorCount; i++) { int a = i; threads[i] = new Thread(() => DoWork_Threaded(a)); threads[i].Start(); } 

这使我的机器上的输出合理。