Frage

Nehmen wir an, ich habe drei Aufgaben, a, b, Und c.Alle drei lösen garantiert zu einem zufälligen Zeitpunkt zwischen 1 und 5 Sekunden eine Ausnahme aus.Ich schreibe dann den folgenden Code:

await Task.WhenAny(a, b, c);

Dadurch wird letztendlich eine Ausnahme von der Aufgabe ausgelöst, die zuerst fehlerhaft ist.Da es keine gibt try...catch Hier wird diese Ausnahme an einer anderen Stelle in meinem Code auftreten.

Was passiert, wenn die verbleibenden zwei Aufgaben eine Ausnahme auslösen?Sind das nicht unbeachtete Ausnahmen, die dazu führen, dass der gesamte Prozess zum Erliegen kommt?Bedeutet das, dass dies die einzige Möglichkeit ist, es zu verwenden? WhenAny ist innerhalb von a try...catch blockieren und dann irgendwie die verbleibenden zwei Aufgaben beobachten, bevor Sie fortfahren?

Nachverfolgen: Ich möchte, dass die Antwort beides auf .NET 4.5 anwendet Und .NET 4.0 mit dem Async Targeting Pack (allerdings eindeutig mit TaskEx.WhenAny In diesem Fall).

War es hilfreich?

Lösung

Was passiert, wenn die verbleibenden zwei Aufgaben eine Ausnahme auslösen?

Diese Tasks wird in einem fehlerhaften Zustand abgeschlossen.

Sind das nicht unbeachtete Ausnahmen, die dazu führen, dass der gesamte Prozess zum Erliegen kommt?

Nicht länger.

In .NET 4.0 ist die Task Der Destruktor würde seine unbeobachtete Ausnahme an übergeben TaskScheduler.UnobservedTaskException, was den Prozess beenden würde, wenn es nicht behandelt wird.

In .NET 4.5 ist dies Verhalten wurde geändert.Jetzt werden unbeobachtete Ausnahmen weitergeleitet TaskScheduler.UnobservedTaskException, aber dann werden sie ignoriert, wenn sie nicht behandelt werden.

Andere Tipps

Ja, die verbleibenden Aufgabenausnahmen werden nicht beobachtet.Vor .NET 4.5 müssen Sie diese beachten (ich bin mir nicht sicher, wie die Situation unter .NET 4.5 ist, aber es hat sich geändert).

Normalerweise schreibe ich mir selbst eine Hilfsmethode für Fire-and-Forget-Aufgaben wie diese:

    public static void IgnoreUnobservedExceptions(this Task task)
    {
        if (task.IsCompleted)
        {
            if (task.IsFaulted)
            {
                var dummy = task.Exception;
            }
            return;
        }

        task.ContinueWith(t =>
            {
                var dummy = t.Exception;
            }, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
    }

Möglicherweise möchten Sie die Protokollierung in Produktions-Apps einbeziehen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top