lambda espressioni sono, per definizione, pigramente valutato in modo che non saranno valutati fino a quando effettivamente chiamato. Nel tuo caso dall'esecuzione dell'attività. Se chiudi un locale nella tua espressione lambda, lo stato del locale al momento dell'esecuzione verrà riflesso. Che è quello che vedi Puoi approfittare di questo. Per esempio. il vostro ciclo for davvero non hanno bisogno di un nuovo lambda per ogni iterazione assumendo per il bene di questo esempio che il risultato descritto era quello che intendeva si potrebbe scrivere
var i =0;
Action<int> action =() => Debug.Print("Error: " + i);
for(;i<50;+i){
Task.Factory.StartNew(action);
}
d'altra parte, se si voleva che in realtà stampato "Error: 1"..."Error 50"
è possibile modificare il precedente per
var i =0;
Func<Action<int>> action = (x) => { return() => Debug.Print("Error: " + x);}
for(;i<50;+i){
Task.Factory.StartNew(action(i));
}
i primi chiude sopra i
e utilizzerà lo stato della i
al momento l'azione viene eseguita e lo stato è spesso andando ad essere lo stato dopo la fine del ciclo. In quest'ultimo caso, i
viene valutato con entusiasmo perché viene passato come argomento a una funzione. Questa funzione restituisce quindi un Action<int>
che viene passato a StartNew
.
Quindi la decisione di progettazione rende possibile sia la valutazione pigramente che la valutazione impaziente. Lazily perché i locali sono chiusi sopra e avidamente perché è possibile forzare locali da eseguire passandoli come argomento o come illustrato di seguito dichiara un altro locale con una portata minore
for (var i = 0; i < 50; ++i) {
var j = i;
Task.Factory.StartNew(() => Debug.Print("Error: " + j));
}
Tutto quanto sopra è generale per lambda. Nel caso specifico di StartNew
ci sia effettivamente un sovraccarico che fa quello che il secondo esempio lo fa in modo che può essere semplificata
var i =0;
Action<object> action = (x) => Debug.Print("Error: " + x);}
for(;i<50;+i){
Task.Factory.StartNew(action,i);
}
fonte
2012-06-15 11:06:25
perché dovrebbero? Sono asincroni comunque. – Vlad
Possibile duplicato "C# Variabile acquisita in loop" http://stackoverflow.com/questions/271440/c-sharp-captured-variable-in-loop –
IMHO, si finisce per fare 2 domande qui - appare il "reale" essere nel titolo (come acquisire il valore, in modo tale che l'attività venga eseguita sul valore al tempo del ciclo), ma il corpo della domanda sembra focalizzarsi su "perché queste cose producono valori imprevisti" (l'effetto di la chiusura cattura il significato che fanno tutti riferimento alla stessa variabile). Quindi, si finisce con la maggior parte delle risposte che spiegano il comportamento invece di rispondere alla tua domanda "reale" (AFAICT :) –