2012-04-16 14 views
15

Scenario: Un compito asincrona in un ciclo esegue un metodo che contiene argomenti che cambiano come il programma continua:Passare argomenti con la modifica dei valori in Attività - Comportamento?

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

Se il ciclo corre più veloce rispetto ai completare le attività, sarà la lista aggiungere il valore corrente della variabile o è la variabile salvata localmente e il valore originale aggiunto?

+3

Controllare questo fuori da Jon Skeet: http://csharpindepth.com/Articles/Chapter5/Closures.aspx –

+0

+1 domanda eccellente! – nawfal

risposta

11

Chiusure chiudono su variabili, non valori. Pertanto, l'incremento _variablepuò alterare il comportamento dell'attività che fa riferimento ad esso.

È possibile evitare questo facendo una copia locale:

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

Oppure si potrebbe passare il valore per l'attività come Stato:

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

Questi sia il lavoro copiando il valore di _variable a una nuova variabile temporanea. Nel primo caso la variabileè definita all'interno dell'ambito del ciclo, quindi ne viene fornita una nuova per ogni iterazione. Nel secondo caso, si effettua una copia del valore di _variable quando si passa all'attività come argomento state. Se _variable fosse un tipo di riferimento, queste soluzioni non funzionerebbero; dovresti eseguire un clone.

+0

Cosa succede se la variabile è un'istanza di una classe? 'SomeClass localVariable = this._variable' all'interno del ciclo. Essendo un riferimento, come faresti ad assicurarti di non ricevere uno stato modificato. – asunrey

+1

@Moyler: dovresti clonare l'istanza all'interno del ciclo, il che significa che devi creare una nuova istanza e rendere i valori delle sue proprietà identiche a quelle dell'istanza originale. –

+0

Grazie, ho avuto bisogno di conferma. Inoltre, originariamente intendevo per il mio esempio avere un tipo di riferimento. Ottimo per ottenere un due per un affare però. – asunrey

Problemi correlati