Ich spiele mit diesen Windows 8 WinRT-Aufgaben und versuche, eine Aufgabe mit der folgenden Methode abzubrechen. Sie funktioniert bis zu einem gewissen Punkt. Die CancelNotification-Methode wird aufgerufen, was den Eindruck erweckt, dass die Aufgabe abgebrochen wurde. Im Hintergrund wird die Aufgabe jedoch weiter ausgeführt. Nach Abschluss wird der Status der Aufgabe immer abgeschlossen und nie abgebrochen. Gibt es eine Möglichkeit, die Aufgabe vollständig anzuhalten, wenn sie abgebrochen wird?
private async void TryTask()
{
CancellationTokenSource source = new CancellationTokenSource();
source.Token.Register(CancelNotification);
source.CancelAfter(TimeSpan.FromSeconds(1));
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token);
await task;
if (task.IsCompleted)
{
MessageDialog md = new MessageDialog(task.Result.ToString());
await md.ShowAsync();
}
else
{
MessageDialog md = new MessageDialog("Uncompleted");
await md.ShowAsync();
}
}
private int slowFunc(int a, int b)
{
string someString = string.Empty;
for (int i = 0; i < 200000; i++)
{
someString += "a";
}
return a + b;
}
private void CancelNotification()
{
}
Antworten:
Informieren Sie sich über Cancellation (das in .NET 4.0 eingeführt wurde und seitdem weitgehend unverändert ist) und das aufgabenbasierte asynchrone Muster , das Richtlinien zur Verwendung
CancellationToken
mitasync
Methoden enthält.Zusammenfassend übergeben Sie
CancellationToken
jeder Methode, die die Stornierung unterstützt, ein a, und diese Methode muss es regelmäßig überprüfen.quelle
CancellationToken
verfügt über alle erforderlichen Hooks, um mit benutzerdefinierten Stornierungssystemen zusammenzuarbeiten, aber nichts kann eine nicht stornierbare Methode abbrechen.Wait
oderResult
inasync
Methoden verwenden; Sie solltenawait
stattdessen immer verwenden , wodurch die Ausnahme korrekt ausgepackt wird.CancellationToken.IsCancellationRequested
Ausnahmen verwendet und stattdessen vorschlägt?Oder um Änderungen zu vermeiden
slowFunc
(sagen wir, Sie haben beispielsweise keinen Zugriff auf den Quellcode):Sie können auch nette Erweiterungsmethoden von https://github.com/StephenCleary/AsyncEx verwenden und es sieht so einfach aus wie:
quelle
ConfigureAwait
Sie es, da Sie sonst in UI-Apps verletzt werden können.using
.Ein Fall, der nicht behandelt wurde, ist die Behandlung der Stornierung innerhalb einer asynchronen Methode. Nehmen wir zum Beispiel einen einfachen Fall, in dem Sie einige Daten in einen Dienst hochladen müssen, um sie zu berechnen und dann einige Ergebnisse zurückzugeben.
Wenn Sie die Stornierung unterstützen möchten, ist es am einfachsten, ein Token zu übergeben und zu überprüfen, ob es zwischen den einzelnen asynchronen Methodenaufrufen abgebrochen wurde (oder ContinueWith verwendet). Wenn es sich um sehr lange laufende Anrufe handelt, können Sie eine Weile warten, bis sie abgebrochen werden. Ich habe eine kleine Hilfsmethode erstellt, die stattdessen fehlschlägt, sobald sie abgebrochen wird.
Um es zu verwenden, fügen Sie es einfach
.WaitOrCancel(token)
zu jedem asynchronen Aufruf hinzu:Beachten Sie, dass die Aufgabe, auf die Sie gewartet haben, dadurch nicht gestoppt wird und weiterhin ausgeführt wird. Sie müssen einen anderen Mechanismus verwenden, um ihn zu stoppen, z. B. den
CancelAsync
Anruf im Beispiel, oder besser noch denselbenCancellationToken
an den übergeben,Task
damit er die Stornierung eventuell verarbeiten kann. Der Versuch, den Thread abzubrechen, wird nicht empfohlen .quelle
UploadDataAsync
im Hintergrund fortgesetzt werden kann, nach Abschluss jedoch nicht mehr aufgerufen wird,CalculateAsync
da dieser Teil bereits nicht mehr wartet). Dies kann für Sie problematisch sein oder auch nicht, insbesondere wenn Sie den Vorgang wiederholen möchten.CancellationToken
Wenn möglich, ist es die bevorzugte Option, den gesamten Weg nach unten zu gehen.Ich möchte nur die bereits akzeptierte Antwort ergänzen. Ich blieb dabei, aber ich ging einen anderen Weg, um das gesamte Ereignis zu bewältigen. Anstatt zu warten, füge ich der Aufgabe einen fertigen Handler hinzu.
Wo der Event-Handler so aussieht
Mit dieser Route ist die gesamte Bearbeitung bereits für Sie erledigt. Wenn die Aufgabe abgebrochen wird, wird nur die Ereignisbehandlungsroutine ausgelöst, und Sie können sehen, ob sie dort abgebrochen wurde.
quelle