2012-03-08 9 views
10

Powiel możliwe:
C# Captured Variable In LoopConfused o wielowątkowości w pętli dla C#

Jestem całkiem nowy, wielowątkowości programowania. Kiedy uruchomiłem poniższy kod i tylko ostatnie dziecko zostało wykonane. Czy ktoś może mi powiedzieć, co się stało? Dziękuję bardzo.

private void Process() 
{ 
    Dictionary<int, int> dataDict = new Dictionary<int, int>(); 
    dataDict.Add(1, 2000); 
    dataDict.Add(2, 1000); 
    dataDict.Add(3, 4000); 
    dataDict.Add(4, 3000); 

    foreach (KeyValuePair<int, int> kvp in dataDict) 
    { 
     Console.WriteLine("Ready for [" + kvp.Key.ToString() + "]"); 
     Task.Factory.StartNew(() => DoSomething(kvp.Value, kvp.Key)); 
    } 

private static void DoSomething(int waitTime, int childID) 
{ 
    {    
     Console.WriteLine("Start task [" + childID.ToString() + "]"); 
     Thread.Sleep(waitTime); 
     Console.WriteLine("End task [" + childID.ToString() + "]"); 
    } 
} 

Wyjście


Ready for [1] 
Ready for [2] 
Ready for [3] 
Ready for [4] 
Start task [4] 
Start task [4] 
Start task [4] 
Start task [4] 
End task [4] 
End task [4] 
End task [4] 
End task [4] 
+0

Ya, aplikacja konsolowa. – Dreteh

Odpowiedz

12

Używając zmiennej pętli w twojej lambda, wszystkie z efektywnie odnoszą się do tej samej zmiennej, która jest ostatnia pozycja słownika u czas uciekają.

Musisz przypisać zmienną pętli do innej zmiennej lokalnej do pętli przed przekazaniem jej do lambda. Zrób to:

foreach (KeyValuePair<int, int> kvp in dataDict) 
{ 
    var pair = kvp; 
    Console.WriteLine("Ready for [" + pair.Key.ToString() + "]"); 
    Task.Factory.StartNew(() => DoSomething(pair.Value, pair.Key)); 
} 

EDYTOWANIE: Wygląda na to, że ta mała pułapka została naprawiona w C# 5. Dlatego może działać dla innych;) Zobacz komentarz przez labroo

+2

ludzie powinni naprawdę wyjaśnić, dlaczego odrzucili, wydaje mi się sensownym wyjaśnieniem dla mnie –

+2

Dlaczego spadł, nie wiem, czy to jest rozwiązanie, ale jest to poprawna zmiana ....... http: //blogs.msdn .com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx – labroo

+0

Zastanawiało się też. Nie widzę niczego złego w mojej odpowiedzi. – Botz3000

1

Możesz temu zapobiec poprzez przypisanie kvp do zmiennej lokalnej w pętli for i przekazać pola zmiennych Key i Value do metody DoSomething.

+0

Dzięki. Też to wymyśliłem, ale po prostu nie rozumiem dlaczego. – Dreteh