2013-08-05 120 views
1

在C#中,如果我执行混淆线程的行为

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

我很可能会获得0223557799,这是奇怪的,因为我是一个INT,我觉得应该在线程开始前被复制。

+1

见埃里克利珀的[关闭了被认为是有害的循环变量(http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable -considered-harmful.aspx)。它主要讨论'foreach',但'for'和(根据顶部注释)存在相同的情况,'foreach'已被更改,但'for'不会(可能) –

+0

而且“我认为它应该是在线程启动之前复制“。你认为你在做什么或谁是副本? –

回答

2

瓶盖是你的问题就在这里。

基本上,当你需要它时,它会抓取它,而不是在你创建时创建(在循环中)。计算机速度非常快,到时候它已经改变了。它不能贯穿整个循环,但它贯穿了整个循环。

这里有一个修复:

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

你拉姆达将被转换成一组,它将处理有指向到我的方法和上下文类的。

1

由于Start()立即返回,i++发生在线程有机会将i打印到控制台之前。我相信,一个解决办法是建立在诚信的本地副本,然后打印:

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

基本上什么正在发生的事情是这样的:

  1. 你希望启动打印的i值的线程。

  2. 线程开始。

  3. 的代码在线程操作得到,如果i值。 请注意,我的值现在可以改变。

  4. i的值被印刷。但没有保证获得逻辑输出。

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

0

我会使用内置的.NET并行支持Task Parallelism

您将不必担心如何管理它为你做的线程。

实施例的代码转换为并行库。

Parallel.For(0, 10, (i, state) => 
{ 
    Console.WriteLine(i); 
});