Ich habe folgendes Beispiel: (Bitte lesen Sie auch Kommentare im Code, da es mehr Sinn ergibt)
%Vor% Nehmen wir an, die Methode PostAsync
von _ mySender
sieht folgendermaßen aus:
Die Frage ist:
Da ich nicht auf die tatsächliche Result
in der MyAsyncMethod
warte und wenn die Methode PostAsync
eine Ausnahme auslöst, in welchem Kontext wird die Ausnahme ausgelöst und behandelt?
und
Gibt es eine Möglichkeit, Ausnahmen in meiner Assembly zu behandeln?
Ich war überrascht, als ich MyAsyncMethod
zu ändern versuchte:
Die Ausnahme wurde hier abgefangen, Ereignis, wenn das tatsächliche Ergebnis nicht erwartet wird. Es kommt vor, dass das Ergebnis von PostAsync
bereits verfügbar ist und die Ausnahme in diesem Kontext geworfen wird, oder?
Kann ContinueWith
verwendet werden, um Ausnahmen in der aktuellen Klasse zu behandeln? Zum Beispiel:
Das sind viele Fragen, die man in eine einzelne "Frage" packen sollte, aber OK ...
Wo löst eine asynchrone Task eine Exception aus, wenn sie nicht erwartet wird?
Nicht beobachtete Ausnahmen für Aufgaben werden vom Ereignis TaskScheduler.UnobservedTaskException
ausgelöst. Dieses Ereignis wird "möglicherweise" ausgelöst, da der Task tatsächlich "Garbage Collected" sein muss, bevor seine Ausnahme als unbehandelt betrachtet wird.
Da ich nicht auf das tatsächliche Ergebnis in MyAsyncMethod warte und die PostAsync-Methode eine Ausnahme auslöst, in welchem Kontext wird die Ausnahme ausgelöst und behandelt?
Jede Methode, die den Modifizierer async
verwendet und eine Task
zurückgibt, wird alle Ausnahmen auf die zurückgegebene Task
anwenden.
Gibt es eine Möglichkeit, Ausnahmen in meiner Assembly zu behandeln?
Ja, Sie könnten die zurückgegebene Aufgabe ersetzen, etwa wie folgt:
%Vor%Ich war überrascht, dass, als ich versuchte, MyAsyncMethod zu ändern, um [die innere Aufgabe synchron zurückzugeben], die Ausnahme hier gefangen wurde, selbst wenn das tatsächliche Ergebnis nicht erwartet wird.
Das bedeutet, dass die Methode, die Sie aufrufen, nicht async Task
ist, wie Ihr Codebeispiel zeigt. Es ist eine Methode, die nicht async
, Task
-returning ist, und wenn eine dieser Methoden eine Ausnahme auslöst, wird sie wie jede andere Ausnahme behandelt (dh sie geht direkt über den Call-Stack, sie wird nicht auf den zurückgegebenen% gesetzt co_de%).
Ist es möglich, ContinueWith zu verwenden, um Ausnahmen in der aktuellen Klasse zu behandeln?
Ja, aber Task
ist sauberer.
Ich verwende eine Erweiterungsmethode für die generische Fehlerbehandlung in Task
. Dies bietet eine Möglichkeit, alle Fehler zu protokollieren und eine benutzerdefinierte Aktion auszuführen, wenn ein Fehler auftritt.
Ich neige dazu, es zu benutzen, wenn ich "fire and forget" Task
:
Da ich nicht auf das tatsächliche Ergebnis in MyAsyncMethod warte und die PostAsync-Methode eine Ausnahme auslöst, in welchem Kontext wird die Ausnahme ausgelöst und behandelt?
Wenn Sie keine der Aufgaben in Ihrem Code await
ausführen oder keine Fortsetzung zuweisen, kann sich das Verhalten je nach verwendeter .NET Framework-Version unterscheiden. In beiden Fällen schluckt das zurückgegebene Task
die Ausnahme, die Differenz tritt bei der Finalisierung auf:
.NET 4.0 - Der Finalizer-Thread wird die geschluckte Ausnahme erneut auslösen. Wenn kein globaler Ausnahmehandler registriert ist, wird der Prozess beendet
.NET 4.5 und höher - Die Ausnahme wird verschluckt und unbemerkt bleiben.
In beiden Fällen TaskScheduler.UnobservedTaskException
Event wird ausgelöst:
Tritt auf, wenn die unbeobachtete Ausnahme einer fehlerhaften Aufgabe eine Ausnahmeskalierungsrichtlinie auslöst, die den Prozess standardmäßig beendet.
Wenn eine non async
Methode zum Zurückgeben von Tasks synchron ausgeführt wird, wird die Exception sofort propagiert, und deshalb fangen Sie die Exception ab, ohne await
zu verwenden, aber Sie sollten definitiv nicht davon abhängig sein das in deinem Code.
Gibt es eine Möglichkeit, Ausnahmen in meiner Assembly zu behandeln?
Ja, das kannst du. Ich würde Sie await
auf Aufgaben raten, die Sie innerhalb Ihrer Versammlung durchführen.
Es gibt keinen Grund, den Modifizierer async
zu verwenden, wenn Sie nichts erwarten:
Dann können Sie await
auf PostAsync
setzen und die Ausnahme dort abfangen:
Sie können diesen Code sogar noch modifizieren und das async
-Schlüsselwort entfernen und möglicherweise die Ausnahme noch höher im Callstack der Methode auffangen, die MyAsyncMethod
aufruft.
Tags und Links .net c# task-parallel-library async-await .net-4.5