In unserer Anwendung arbeiten wir viel mit async / await und Tasks. Daher verwendet es häufig Task.Run, manchmal mit Unterstützung für die Löschung unter Verwendung des eingebauten CancellationToken
.
Wenn ich jetzt die Ausführung mit dem CancellationToken abbringe, stoppt die Ausführung am Anfang der nächsten Schleife, oder wenn die Aufgabe überhaupt nicht gestartet wurde, löst sie eine Ausnahme aus (TaskCanceledException in Task.Run). Die Frage ist nun, warum Task.Run eine Exception verwendet, um die erfolgreiche Löschung zu steuern, anstatt nur eine abgeschlossene Aufgabe zurückzugeben. Gibt es einen bestimmten Grund, warum MS sich nicht an die Regel "KEINE AUSNAHMEN ZUR KONTROLLE DES AUSFÜHRUNGSFLUSSES VERWENDEN?" Gehalten hat?
Und wie kann ich vermeiden, dass jede Methode, die die Annullierung unterstützt (was eine Menge ist), in einem völlig nutzlosen try catch (TaskCancelledException) -Block ist?
Nun, Sie können den Unterschied in Ihrem sehr einfachen Szenario nicht wirklich sehen - Sie verwenden nicht das Ergebnis von Task
, und Sie müssen die Löschung nicht über einen komplexen Aufruf-Stack verbreiten.
Erstens kann Ihr Task
einen Wert zurückgeben. Was geben Sie zurück, wenn der Vorgang abgebrochen wurde?
Zweitens gibt es möglicherweise andere Aufgaben, die auf Ihre abgebrochene Aufgabe folgen. Wahrscheinlich möchten Sie die Löschung durch die anderen Aufgaben nach Belieben verbreiten.
Ausnahmen verbreiten sich. Der Abbruch der Aufgabe ist in dieser Verwendung fast identisch mit Thread.Abort
- wenn Sie Thread.Abort
ausgeben, wird ein ThreadAbortException
verwendet, um sicherzustellen, dass Sie den gesamten Weg bis zum Anfang zurückgelegt haben. Andernfalls müssten alle Ihre Methoden das Ergebnis jeder aufgerufenen Methode überprüfen, prüfen, ob sie abgebrochen wurde, und sich bei Bedarf selbst zurückgeben - und wir haben bereits gesehen, dass die Leute die Fehlerrückgabewerte im alten C ignorieren:
Am Ende ist das Abbrechen von Aufgaben genau wie das Abbrechen von Threads ein Ausnahmefall. Es beinhaltet bereits Synchronisation, Stapelabwickeln usw.
Dies bedeutet jedoch nicht, dass Sie unbedingt try-catch
verwenden müssen, um die Ausnahme abzufangen - Sie können Task-Status verwenden. Zum Beispiel können Sie eine Hilfsfunktion wie folgt verwenden:
Was Sie als
verwenden können %Vor%Natürlich sollte noône Sie dazu zwingen, diese Methode der Stornierung zu verwenden - sie wird einfach als Annehmlichkeit zur Verfügung gestellt. Sie können beispielsweise Ihren eigenen verstärkten Typ verwenden, um die Stornierungsinformationen beizubehalten, und die Stornierung manuell vornehmen. Aber wenn Sie damit anfangen, werden Sie den Grund finden, warum die Löschung mit Ausnahmen gehandhabt wird - dies im imperativen Code zu tun ist ein Schmerz, so dass Sie entweder viel Mühe für keinen Gewinn verschwenden, oder Sie werden zu einem wechseln mehr funktionale Art der Programmierung (komm, wir haben Cookies! *).
(*) Haftungsausschluss: Wir haben keine Cookies. Aber Sie können Ihre eigenen machen!
Die Ausnahme wird zu einem bestimmten Zweck ausgelöst, da andere in der Community bereits darauf hingewiesen haben.
Wenn Sie jedoch mehr Kontrolle über das Verhalten von TaskCanceledException
haben möchten und dennoch die Logik isoliert an einem Ort haben, können Sie eine Extension-Methode implementieren, um Task
zu erweitern, was die Annullierung ähnlich macht -
Tags und Links c# task-parallel-library async-await cancellation-token