2010-07-19 6 views
9

Je possède ce code:de 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(); 
     } 

la fonction k est la suivante:

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

pour une raison que le dernier fil est en cours d'exécution et l'impression 4444444 .... pourquoi les threads ne sont-ils pas tous en cours d'exécution?

+9

Ce doit être la variante la plus absconse de la norme fermeture sur la boucle variable question que j'ai jamais vu. –

+0

Celui-ci est encore plus similaire: http://stackoverflow.com/questions/1930133/c-closures-why-is-the-loopvariable-captured-by-reference –

+0

Connexe: "Fermeture sur la boucle variable considérée comme nuisible" par Eric Lippert. http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx –

Répondre

22

Tous les threads impriment la même variable.

Votre expression lambda (() => c1.k(i)) capture la variable i par référence. Par conséquent, lorsque l'expression lambda s'exécute après i++, elle prend la nouvelle valeur i.

Pour résoudre ce problème, vous devez déclarer une variable séparée à l'intérieur de la boucle de sorte que chaque lambda obtient sa propre variable, comme ceci:

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

+1 pour cette réponse. C'est fondamentalement le même que celui de Winston, mais l'explication est plus détaillée. – schnaader

+0

Sur une note de côté: certaines langues comme F # ne compileront pas si vous essayez de capturer une variable mutable dans une fermeture. – gradbot

4

Vous clôturez sur la variable i.

Essayez plutôt

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