C# 为什么循环中的任务工厂打印超出循环索引?

C# 为什么循环中的任务工厂打印超出循环索引?,c#,task-parallel-library,C#,Task Parallel Library,我正在学习使用C#中的任务并行库(TPL),并编写了以下代码(您可以复制并运行它) 然而,在另一次发布中(代码没有更改),我得到了以下信息: in loop: i = 1 in loop: i = 1 in loop: i = 2 in loop: i = 3 in loop: i = 4 in loop: i = 5 press any key to terminate... 这是有道理的 我调试了代码,发现I值为:0,1,3,4,5,6 这是怎么发生的? 我为什么(i=6)进入循环? 我的

我正在学习使用C#中的任务并行库(TPL),并编写了以下代码(您可以复制并运行它)

然而,在另一次发布中(代码没有更改),我得到了以下信息:

in loop: i = 1
in loop: i = 1
in loop: i = 2
in loop: i = 3
in loop: i = 4
in loop: i = 5
press any key to terminate...
这是有道理的

我调试了代码,发现
I
值为:
0,1,3,4,5,6

这是怎么发生的?

我为什么(i=6)进入循环?

我的代码有什么错误吗?


注意:我使用的是visual studio 2010

很明显,当执行代码(带有Console.WriteLine语句的委托)时,您将按原样打印“I”的值,这很可能是在稍晚的时候

这是您想要的:

for (int i = 0; i < 6; i++)
{
  var j = i;
  var t01 = Task.Factory.StartNew(() => Console.WriteLine("in loop: i = {0}", j));
}
for(int i=0;i<6;i++)
{
var j=i;
var t01=Task.Factory.StartNew(()=>Console.WriteLine(“在循环中:i={0}”,j));
}
>我的代码有什么错误吗?


是:-)

因为存在关闭问题。您需要在临时变量中复制变量
i

for (int i = 0; i < 6; i++)
{
    var tempi = i;
    var t01 = Task.Factory.StartNew(() => Console.WriteLine("in loop: i = {0}", tempi));
}
for(int i=0;i<6;i++)
{
var-tempi=i;
var t01=Task.Factory.StartNew(()=>Console.WriteLine(“在循环中:i={0}”,tempi));
}
因为你的任务是从另一个线程开始的。但您不会在当前线程中等待该任务。因此程序将返回并增加计数器。由于您创建的代理使用原始计数器,因此它将打印
6
。因为数到6比创建新任务要快得多


当您使用调试器时,新任务将有机会在您继续递增计数器之前打印值,

使用该代码,您可以获得一个工作示例,说明在编程多线程应用程序时必须注意的事项。问题是启动thead需要一些时间,在这段时间内,主线程完成了对
for循环的迭代。当主线程完成
i==6
时,每个线程访问
i
的值,即6。解决方案是生成一个局部变量并复制
i

for(...)
{
    int temp = i;
    var t1 //.....
}
-例如

在循环中声明变量是我在循环中得到(i=6)的原因之一。

所有步骤:

i=0
i<6 => create Thread1
i++ => i=1
i<6 => create Thread2
i++ => i=2
i<6 => create Thread3
i++ => i=3
i<6 => create Thread4
i++ => i=4
i<6 => create Thread5
i++ => i=5
i<6 => create Thread6
i++ => i=6
i<6 NO => leave for
创建的所有6个线程都将执行:
Console.WriteLine(“in-loop:i={0}”,i)
wherei=6

@HansKesting,我知道这个问题。foreach将在内部声明变量。请读一下。你是对的,我忘了。你可能想在你的答案中加上解释。你是对的,这确实有效,但是,我在操作系统层面上寻找发生这一切的原因。
for(...)
{
    int temp = i;
    var t1 //.....
}
for (int i = 0; i < 6; i++)
foreach (int i in Enumerable.Range(0, 6))
i=0
i<6 => create Thread1
i++ => i=1
i<6 => create Thread2
i++ => i=2
i<6 => create Thread3
i++ => i=3
i<6 => create Thread4
i++ => i=4
i<6 => create Thread5
i++ => i=5
i<6 => create Thread6
i++ => i=6
i<6 NO => leave for
Console.WriteLine("press any key to terminate...");