2010-07-19 23 views
9

ich habe diesen Code:Array von Threads C#

Thread[] threadsArray = new Thread[4]; 
     for (int i = 0; i < 4; i++) 
     { 
      threadsArray[i] = new Thread(() => c1.k(i)); 
     } 
     for (int i = 0; i < 4; i++) 
     { 
      threadsArray[i].Start(); 
     } 
     for (int i = 0; i < 4; i++) 
     { 
      threadsArray[i].Join(); 
     } 

die Funktion k ist dies:

void k(int i) 
{ 
    while(true) 
     Console.WriteLine(i); 
} 

aus irgendeinem Grund nur der letzte Thread ausgeführt wird und das Drucken 4444444 .... warum laufen nicht alle Threads?

+9

dies die oddball Variante der Standard-Schließ-over-the-Loop-Variable Frage sein, die ich je gesehen habe. –

+0

Dieser ist noch ähnlicher: http://stackoverflow.com/questions/1930133/c-closures-why-is-the-loopvariable-captured-by-reference –

+0

Related: "Schließen über die Schleife Variable als schädlich" von Eric Lippert. http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-consided-harmful.aspx –

Antwort

22

Alle Threads drucken dieselbe Variable.

Ihr Lambda-Ausdruck (() => c1.k(i)) erfasst die i Variable als Referenz.
Wenn der Lambda-Ausdruck nach i++ ausgeführt wird, wird daher der neue Wert i übernommen.

Um dies zu beheben, müssen Sie eine separate Variable innerhalb der Schleife erklären, so dass jeder Lambda eine eigene Variable wird, wie folgt aus:

for (int i = 0; i < 4; i++) 
    { 
     int localNum = i; 
     threadsArray[i] = new Thread(() => c1.k(localNum)); 
    } 
+3

+1 für diese Antwort. Es ist im Grunde das gleiche wie Winston, aber die Erklärung ist detaillierter. – schnaader

+0

Nebenbei bemerkt: einige Sprachen wie F # kompilieren nicht, wenn Sie versuchen, eine veränderbare Variable in einer Schließung zu erfassen. – gradbot

4

Sie werden über die Variable i zu schließen.

Versuchen Sie stattdessen

for (int i = 0; i < 4; i++) 
{ 
    int x = i; 
    threadsArray[i] = new Thread(() => c1.k(x)); 
}