2012-11-08 6 views
9

Ich habe den folgenden Code in C#, VS2012, WPF 4.5. Meine Erwartung wäre, dass .ContinueWith ausgeführt wird, nachdem die Aufgabe vollständig abgeschlossen wurde (das ist der ganze Zweck einer Fortführung, nicht wahr?)..Continue startet, bevor die Aufgabe abgeschlossen ist

Dies sollte einen Wert von 2 in finalResult ergeben.

int myTestInt = 0; 

Task task = Task.Factory.StartNew(async() => 
{ 
    myTestInt = 1; 
    await Task.Delay(TimeSpan.FromSeconds(6)); 
    myTestInt = 2; 

}).ContinueWith(_ => 
    { 
     int finalResult = myTestInt; 
    }); 

Tatsächlich wird finalResult stattdessen der Wert 1 zugewiesen. So scheint es, als ob die Fortsetzung bereits auf der await-Anweisung gestartet wurde.

Ist dies das beabsichtigte Verhalten? Fehle ich hier etwas? Kann ich nicht auf ContinueWith starten, nachdem eine Aufgabe vollständig abgeschlossen ist?

Update:

Justins Antwort inspiriert mich nur folgendes zu überprüfen:

int myTestInt = 0; 
Task task=Task.Factory.StartNew(async() => 
{ 
    myTestInt = 1; 
    await Task.Delay(TimeSpan.FromSeconds(6)); 
    myTestInt = 2; 
}); 

task.Wait(); 
int result2 = myTestInt; 

finalResult noch auf 1 gesetzt ist Gibt es keine Möglichkeit für eine Aufgabe zuverlässig zu warten, der await s enthält abzuschließen ?

+4

Ich denke, Sie sollten 'Task.Delay' direkt aufrufen - nicht mit dem' erwarten' Schlüsselwort. –

+2

Sie werden feststellen, dass '_' ist eigentlich eine 'Task ', die vollständig unterstützt, was Justin sagt ... –

+0

In der Tat wird die Verwendung von Task.Delay (6) das erwartete Ergebnis erzeugen, wird aber nicht 6 Sekunden warten . Ich denke, es wäre genauso, die ganze Zeile zu löschen. –

Antwort

10

Wenn Sie einen async Delegierten Task.Factory.StartNew geben, stellt das zurück Task nur den ersten Teil dieser Delegierten (bis zu der Zeit etwas, das es await s, die nicht bereits abgeschlossen ist).

Wenn Sie jedoch einen async Delegaten an die neue Task.Run-Methode übergeben (die aus diesem Grund enthalten war), entspricht der zurückgegebene Task dem gesamten Delegaten. So können Sie ContinueWith verwenden, wie Sie erwarten. (Obwohl await ist normalerweise eine bessere Option als ContinueWith). Weitere Informationen zu StartNew vs Run finden Sie unter Stephen Toub's post on the topic.

+0

Der verlinkte Beitrag macht es sehr deutlich. Vielen Dank!! –

4

Der await gibt sofort die Kontrolle an die aufrufende Funktion zurück, die in diesem Fall der StartNew Ihrer Aufgabe ist. Dies bedeutet, dass die Aufgabe dann den ContinueWith-Befehl vervollständigt und ausführt. Wenn Sie wirklich möchten, dass die Aufgabe vor dem ContinueWith abgeschlossen wird, warten Sie nicht auf die Task.Delay.

+0

Ich denke, du hast Recht - warten markiert die aktuelle Aufgabe als abgeschlossen. Obwohl es nicht (zumindest nicht aus einer semantischen Sicht) ist. Da heute ein Grundbaustein der gesamten Software vorhanden ist, bedeutet das, sich nie mehr auf ContinueWith zu verlassen. Denkst du nicht, das ist ein Käfer? –

-1

Ich sah dies in der MSDN: :-)

public async void button1_Click(object sender, EventArgs e) 
{ 
    pictureBox1.Image = await Task.Run(async() => 
    { 
     using(Bitmap bmp1 = await DownloadFirstImageAsync()) 
     using(Bitmap bmp2 = await DownloadSecondImageAsync()) 
     return Mashup(bmp1, bmp2); 
    }); 
} 

Also vergessen Sie nicht die "async()" !!!

+0

Sein Code hat die 'async' sein Problem ist, er' TaskFactory' verwendet, die keine Überladung hat, die eine 'Func ' oder eine 'Func >' die 'Task.Run' hat. –

Verwandte Themen