在 C# 中,如果我执行
for (int i = 0;i < 10;i++)
new Thread(() => Console.Write(i)).Start();
我可能会得到 0223557799,这很奇怪,因为 i 是一个 int,我认为应该在线程开始之前复制它。
在 C# 中,如果我执行
for (int i = 0;i < 10;i++)
new Thread(() => Console.Write(i)).Start();
我可能会得到 0223557799,这很奇怪,因为 i 是一个 int,我认为应该在线程开始之前复制它。
闭包是你的问题。
基本上,不是在创建lambda(在循环中)时获取值,而是在需要时获取它。计算机的速度如此之快,以至于发生这种情况时,它已经发生了变化。它不能遍历整个循环,但它会遍历其中的一部分。
这是一个修复:
for (int i = 0; i < 10; i++)
{
var n = i;
new Thread(() => Console.Write(n)).Start();
}
因为Start()
立即返回,所以i++
发生在线程有机会打印i
到控制台之前。我相信一种解决方法是创建 int 的本地副本,然后打印:
for (int i = 0;i < 10;i++) {
int j = i;
new Thread(() => Console.Write(j)).Start();
}
基本上发生的事情是这样的:
您想启动一个打印i
.
线程开始。
线程中运行的代码获取值 if i
。请注意,现在可以更改 i 的值。
的值i
被打印出来。但不能保证得到逻辑输出。
首先将 i 的值复制到另一个变量中,然后打印该值。其他答案提供了足够的示例代码。
您的 lambda 将被翻译成一组方法和上下文类,它们将处理对 i 的引用。
我会使用内置的 .NET 并行支持任务并行
您不必担心管理它为您完成的线程。
示例您的代码转换为并行库。
Parallel.For(0, 10, (i, state) =>
{
Console.WriteLine(i);
});