Ein Lambda, das eine äußere Variable verwendet, erfasst tatsächlich die Variable, nicht den darin gespeicherten Wert. Das bedeutet, dass mit fortschreitender Schleife auch der Wert geändert wird, den Sie aus der erfassten Variablen lesen würden.
Sie können dies beheben, indem Sie eine temporäre Variable in der Schleife verwenden. Ihr Code wäre viel sauberer sein aber wenn Sie async/await
statt ContinueWith und Lambda-Ausdrücke verwendet werden, zB:
for (int i=0;i<N;i++)
{
//...
var result=await thatOtherAsyncMethod(...);
ProcessResult(i, result));
}
In der Regel können Sie Capture-Probleme vermeiden, durch Kopieren des Schleifenvariable in eine Variable innerhalb der Schleife des Oszilloskops definiert.
Dies behebt das Problem, da die temporäre Variable nur innerhalb des Körpers der Schleife existiert. Die Lambda ist auch innerhalb der Schleife des Körpers erstellt und erfasst eine lokale, unveränderliche Variable:
for (int i=0;i<N;i++)
{
var temp=i;
var myLambda = new Action(()=>MyMethod(temp));
//This runs with the local copy, not i
myLambda();
}
Ein noch besserer Weg aber ist zu vermeiden erfasst und die Schleife Wert als Zustandsparameter zu ContinueWith
passieren, zB:
for (int i = 0; i < N; ++i)
{
//...
var task = anotherTask.ContinueWith(
(t,state) => ProcessResult((int)state, t.Result),
i);
//...
}
Warum benutzen Sie 'ContinueWith' anstatt zu warten? Wie für "i" erfasst Ihr Lambda die * Variable * nicht den Wert der Variablen. Das Lesen von "i" gibt das zurück, was "i" enthält, wenn Sie es tatsächlich lesen - wenn der Aufruf von 'ProcessResult (i, ..)' tatsächlich ausgeführt wird. Dies ist übrigens das erwartete Verhalten. Mit 'erwarten' wird dies behoben, indem Sie das Lambda loswerden * und * Ihren Code vereinfachen –
Um die Aufgaben zu verketten. Diese können lange laufen, während warten würde, den aktuellen Thread zu suspendieren. – Hector
Nein, wird es nicht. 'erwarten' * wartet *, es blockiert nicht.Es ist das Äquivalent von 'ContinueWith', nicht' Wait'. Es macht das Verketten * viel * einfacher * weil es keine Lambdas und Captures benötigt. –