2012-04-16 8 views
15

Escenario: Una tarea asíncrona en un bucle ejecuta un método que contiene argumentos que cambian a medida que el programa sigue:Pasar argumentos con valores cambiantes a Tarea - ¿Comportamiento?

while(this._variable < 100) 
{ 
    this._variable++; 
    var aTask = Task.Factory.StartNew(() => 
    { 
     aList.add(this._variable); 
     update(this._savePoint); 
    }); 
} 

Si el bucle se ejecuta más rápido que las tareas completas, será la lista de agregar el valor actual de la variable o ¿La variable se guarda localmente y se agrega el valor original?

+3

Mira esto por Jon Skeet: http://csharpindepth.com/Articles/Chapter5/Closures.aspx –

+0

+1 excelente pregunta! – nawfal

Respuesta

11

Los cierres se cierran sobre las variables, no sobre los valores. Por lo tanto, al incrementar _variablepuede alterar el comportamiento de la tarea que se refiere a ello.

Esto se puede evitar haciendo una copia local:

while (this._variable < 100) 
{ 
    this._variable++; 
    int local = _variable; 
    var aTask = Task.Factory.StartNew(() => 
    { 
     aList.add(local); 
     update(this._savePoint); 
    }); 
} 

O usted podría pasar el valor de la tarea como Estado:

while (this._variable < 100) 
{ 
    this._variable++; 
    var aTask = Task.Factory.StartNew(object state => 
    { 
     aList.add((int)state); 
     update(this._savePoint); 
    }, this._variable); 
} 

Estos dos trabajos copiando el valor de _variable a una nueva variable temporal. En el primer caso, la variable local se define dentro del alcance del ciclo, por lo que se obtiene una nueva para cada iteración. En el segundo caso, realiza una copia del valor de _variable cuando lo pasa a la tarea como el argumento state. Si _variable fuera un tipo de referencia, estas soluciones no funcionarían; tendrías que realizar un clon.

+0

¿Qué pasa si la variable es una instancia de una clase? 'SomeClass localVariable = this._variable' dentro del ciclo. Al ser una referencia, ¿cómo se aseguraría de no recibir un cambio de estado? – asunrey

+1

@Moyler: tendrías que clonar la instancia dentro del ciclo, lo que significa que creas una nueva instancia y haces que los valores de sus propiedades sean idénticos a los de la instancia original. –

+0

Gracias, necesitaba eso confirmado. Además, originalmente quise que mi ejemplo tuviera un tipo de referencia. Sin embargo, es genial conseguir una oferta de dos por uno. – asunrey

Cuestiones relacionadas