2014-02-24 60 views
-3

在c#中定義了這種行爲嗎?在lambdas中使用循環變量

static void Main(string[] args) 
{ 
    for (int i = 0; i < 10; i++) 
    { 
     Task.Run(() => Console.WriteLine("This is task " + i)); 
    } 

    Console.ReadLine(); 
} 

輸出

This is task 10 
This is task 10 
This is task 10 
This is task 10 
This is task 10 
This is task 10 
This is task 10 
This is task 10 
This is task 10 
This is task 10 

我知道如何解決它,我知道爲什麼會發生,但它是一個定義的行爲?

+1

@TimSchmelter _I知道如何解決它,我知道它爲什麼發生。 – Gusdor

+2

你是什麼意思的「定義的行爲?」 –

+2

@gusdor:所以你有沒有看過這個答案和它提供的eric lippert博客的鏈接?如果是這樣,你不明白哪一部分? –

回答

5

不,這是沒有定義的行爲。這是一個競賽條件,其中每個輸出可能是任何值從0到10,在任何命令。它取決於生成的任務對主程序的執行時間;這反過來又主要取決於您的機器的多處理功能。如果任務碰巧被工作者線程拾取並且在之前執行循環已完成,那麼您將在該時間點得到循環計數器中發生的任何值。

你經常得到循環計數器的最終值的原因是主循環在計算上是微不足道的,並且在任何任務有機會運行之前完成。如果你想觀察不確定性,人爲延遲添加到循環:在Intel酷睿i7

for (int i = 0; i < 10; i++) 
{ 
    Task.Factory.StartNew(() => Console.WriteLine("This is task " + i)); 
    Thread.SpinWait(20000); 
} 

輸出示例:

This is task 2 
This is task 3 
This is task 3 
This is task 3 
This is task 4 
This is task 5 
This is task 7 
This is task 8 
This is task 9 
This is task 8 

如果你使用一個足夠大的延誤,任務將有機會以直觀的預期順序運行,輸出0, 1, 2, ..., 9

+0

+1你是對的錢:) –

+1

@RobertHarvey:輸出是一次運行。它在隨後的運行中可能會改變。 – Douglas