2014-01-17 8 views
6

Dies ist eine Fortsetzung von dieser Frage: Multiple Task ContinuationAufgabe abgebrochen Exception (ThrowForNonSuccess)

Ich habe meinen Code wie in der Antwort geändert, aber jetzt habe ich TaskCancelledExceptions erhalte, wenn ich versuche Aufgaben auszuführen.

public virtual async Task RunAsync(TaskWithProgress task) 
{ 
    Show(); 
    TaskIsRunning(); 
    await SetCompletedHandler(TaskComplete()); 
    await SetCancelledHandler(TaskCancelled()) 
    await SetFaultedHandler(TaskFaulted()); 
    await task; 
    Close(); 
} 

jedoch der folgende Code nicht. Ich bin ein bisschen fest, warum.

public virtual Task RunAsync(TaskWithProgress task) 
{ 
    Show(); 
    TaskIsRunning(); 
    SetCompletedHandler(TaskComplete()); 
    SetCancelledHandler(TaskCancelled()) 
    SetFaultedHandler(TaskFaulted()); 
    return task; 
} 

Der Aufrufcode umfasst im Wesentlichen die folgenden:

await progressDialog.RunAsync(task); 

Edit:

ich kündigen keine cancellationtoken überall so kann ich nicht sehen, warum dies, dass die Ausnahme wirft.

Die drei SetXXXHandler() Methoden führen im wesentlichen den folgenden Code mit verschiedenen Fortsetzung Status:

task.ContinueWith(_ => action(), CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, this.Scheduler); 

Der Stack-Trace ist hier:

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
    at FugroDXExt.frmBaseProgressAsync.<RunAsync>d__7.MoveNext() in d:\C#\FugroDXExt\trunk\frmBaseProgressAsync.cs:line 92 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
    at FCP.Forms.frmProcessing.<mnuApplyCenteredSmoothing_ItemClick>d__34.MoveNext() in d:\C#\FCP\FCP\Forms\frmProcessing.cs:line 578 

Close() schließt einfach das Formular aus. Wenn ich diese Zeile entferne, passiert das Gleiche.

+0

Höchstwahrscheinlich wird irgendwo ein Code storniert ein 'CancellationToken'. –

+0

Das ist das seltsame Ding, es ist nicht. Ich hakte meine 'cancellationToken.Cancel()' aus und es tritt immer noch auf. – Simon

+0

Was ist der Stack-Trace? Und was macht Close() so hier? – Heath

Antwort

8

Sie sagen, SetCancelledHandler fügt nur eine Fortsetzung der Aufgabe hinzu. Ich nehme an, das ist die gleiche Aufgabe RunAsync bekommt als Parameter, obwohl ich nicht durch Ihren Code sagen kann, wie SetCancelledHandler bekommt eine Aufgabe weiter (ich nehme an, dass wir etwas Code fehlen). Anyways ...

Sie registrieren 3 Fortsetzungen für eine Aufgabe, die ausgeführt wird, wenn die Aufgabe abgeschlossen ist, abgebrochen wird und fehlerhaft ist. Angenommen, die ursprüngliche Aufgabe wurde erfolgreich ausgeführt, ohne abgebrochen zu werden. Das bedeutet, dass 2 Ihrer Fortsetzungen (OnCanceled und OnFaulted) nicht ausgeführt werden, weil sie nicht sein müssen. Die Möglichkeit, eine Aufgabe nicht in der TPL auszuführen, besteht darin, sie abzubrechen, und zwar automatisch.

Der Unterschied zwischen Ihren 2 Code-Schnipsel ist, dass in der ersten Sie await die Aufgabenfortsetzungen, und sie abgebrochen werden, die Ihre Ausnahme erklärt. Auf das zweite Snippet warten Sie nicht auf die Fortsetzungen, nur auf die ursprüngliche Aufgabe, die erfolgreich abgeschlossen wurde.

P.S: Ich denke, die zweite Option ist passender. Sie brauchen await all diese Fortsetzungen nicht. Sie wollen sie laufen lassen, wenn sie müssen.

TL; DR: Sie await eine abgebrochene Fortsetzungsaufgabe. Die Fortsetzungsaufgabe, nicht das Original, löst eine Ausnahme aus.

+1

Das macht Sinn, danke – Simon

+1

@Simon Jederzeit ... – i3arnon

Verwandte Themen