2014-04-04 24 views
1

我寫的代碼:任務和增值

List<Task> tt = new List<Task>(); 
for (int i = 0; i < 5; i++) 
{ 
    tt.Add(
    new Task((o) => 
    { 
     Thread.Sleep(Convert.ToInt32(o)*1000); 
     Console.WriteLine("end of {0}!", Convert.ToInt32(o)); 
    },i)); 
} 

tt.ForEach(t => t.Start()); 
Task.WaitAll(tt.ToArray()); 

,並告訴我在控制檯:1 結束! (間隔1秒)

2結束! (間隔1秒)

3結束! (間隔1秒)

4結束! (間隔1秒)

5的結尾! (間隔1秒)

,但如果我得到這個代碼:

List<Task> tt = new List<Task>(); 
for (int i = 0; i < 5; i++) 
{ 
    tt.Add(
    new Task(() => 
    { 
     Thread.Sleep(i*1000); 
     Console.Write("end! "); 
    })); 
} 

tt.ForEach(t => t.Start()); 
Task.WaitAll(tt.ToArray()); 

然後我有這樣的回答: (間隔5秒,都在同一個時刻): 結束! 結束! 結束! 結束! 結束!

你能解釋我這種現象嗎?

我認爲:

這是由於該變量「i」是連續增加和線程可以訪問的變量?在這種情況下,每個線程都會記住最後一個值「i」,這樣每個線程將等待5秒鐘,然後發送一條消息?

這是很好的理由?

+0

是的,你」我得到了一個由所有任務捕獲的「i」變量。如果你在loop中聲明瞭一個局部變量*,它需要一個'i'的副本,並且在你的lambda表達式中使用這個副本,那就沒事了。 –

回答

0

在使用的i的最後一個值第二種情況是5由於capture closure of loop variable,您可以循環變量的值賦給一些局部變量和使用,在任務,

List<Task> tt = new List<Task>(); 
for (int i = 0; i < 5; i++) 
{ 
    int temp = i; 
    tt.Add(
    new Task(() => 
    { 
     Thread.Sleep(temp * 1000); 
     Console.Write("end! "); 
    })); 
} 

tt.ForEach(t => t.Start()); 
Task.WaitAll(tt.ToArray());