C#中的线程:如何保持循环索引线程安全?
在下面的示例中,似乎for循环的索引i
由每个线程独立修改,导致DoWork_Threaded()
的i
奇怪值(倍数,甚至大于System.Environment.ProcessorCount-1
值DoWork_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(); }
这使我的机器上的输出合理。