1

在 C# 中,如果我执行

for (int i = 0;i < 10;i++)
    new Thread(() => Console.Write(i)).Start();

我可能会得到 0223557799,这很奇怪,因为 i 是一个 int,我认为应该在线程开始之前复制它。

4

5 回答 5

2

闭包是你的问题。

基本上,不是在创建lambda(在循环中)时获取值,而是在需要时获取它。计算机的速度如此之快,以至于发生这种情况时,它已经发生了变化。它不能遍历整个循环,但它会遍历其中的一部分。

这是一个修复:

for (int i = 0; i < 10; i++) 
{
    var n = i;
    new Thread(() => Console.Write(n)).Start();
}
于 2013-08-05T06:48:36.983 回答
1

因为Start()立即返回,所以i++发生在线程有机会打印i到控制台之前。我相信一种解决方法是创建 int 的本地副本,然后打印:

for (int i = 0;i < 10;i++) {
    int j = i;
    new Thread(() => Console.Write(j)).Start();
}
于 2013-08-05T06:45:10.310 回答
1

基本上发生的事情是这样的:

  1. 您想启动一个打印i.

  2. 线程开始。

  3. 线程中运行的代码获取值 if i请注意,现在可以更改 i 的值。

  4. 的值i被打印出来。但不能保证得到逻辑输出。

首先将 i 的值复制到另一个变量中,然后打印该值。其他答案提供了足够的示例代码。

于 2013-08-05T06:49:02.153 回答
0

您的 lambda 将被翻译成一组方法和上下文类,它们将处理对 i 的引用。

于 2013-08-05T06:43:18.797 回答
0

我会使用内置的 .NET 并行支持任务并行

您不必担心管理它为您完成的线程。

示例您的代码转换为并行库。

Parallel.For(0, 10, (i, state) =>
{
    Console.WriteLine(i);
});
于 2013-08-05T07:00:16.813 回答