2010-07-19 15 views
9

tengo este código:serie de roscas 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 función k es la siguiente:

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

por alguna razón sólo el último hilo está en funcionamiento y la impresión 4444444 .... qué no están todos los hilos en ejecución?

+9

Esto tiene que ser la variante más excéntrica del cierre-over-the-loop variable pregunta estándar que he visto nunca. –

+0

Este es aún más similar: http://stackoverflow.com/questions/1930133/c-closures-why-is-the-loopvariable-captured-by-reference –

+0

Relacionado: "Cierre de la variable de bucle considerado perjudicial" por Eric Lippert. http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx –

Respuesta

22

Todos los hilos están imprimiendo la misma variable.

Su expresión lambda (() => c1.k(i)) captura la variable i por referencia.
Por lo tanto, cuando la expresión lambda se ejecuta después de i++, toma el nuevo valor de i.

Para solucionar este problema, tiene que declarar una variable separada dentro del bucle de manera que cada lambda obtiene su propia variable, así:

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

+1 para obtener esta respuesta. Es básicamente lo mismo que Winston, pero la explicación es más detallada. – schnaader

+0

En una nota al margen: algunos lenguajes como F # no se compilarán si intenta capturar una variable mutable en un cierre. – gradbot

4

Se dispone a cerrar sobre la variable i.

Tal vez puedas probar

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