Die Ausnahme (n) einer Aufgabe wurden weder beim Warten auf die Aufgabe noch beim Zugriff auf ihre Ausnahmeeigenschaft beobachtet. Infolgedessen war die unbeobachtete Ausnahme


100

Was bedeutet das und wie kann es behoben werden?

Ich verwende TPL-Aufgaben.

Der ganze Fehler

Die Ausnahme (n) einer Aufgabe wurden weder beim Warten auf die Aufgabe noch beim Zugriff auf ihre Ausnahmeeigenschaft beobachtet. Infolgedessen wurde die nicht beobachtete Ausnahme vom Finalizer-Thread erneut ausgelöst.

bei System.Threading.Tasks.TaskExceptionHolder.Finalize ()

mscorlib

Antworten:


158

Wenn Sie eine Aufgabe erstellen und niemals task.Wait()das Ergebnis von a aufrufen oder versuchen, es abzurufen Task<T>, wird die Anwendung während der Finalisierung heruntergefahren, wenn die Aufgabe vom Garbage Collector erfasst wird. Weitere Informationen finden Sie auf der MSDN-Seite zur Ausnahmebehandlung in der TPL .

Die beste Option hier ist, die Ausnahme zu "behandeln". Dies kann über eine Fortsetzung erfolgen. Sie können der Aufgabe eine Fortsetzung hinzufügen und die auftretende Ausnahme protokollieren / schlucken / usw. Dies bietet eine saubere Möglichkeit, Aufgabenausnahmen zu protokollieren, und kann als einfache Erweiterungsmethode geschrieben werden, z.

public static void LogExceptions(this Task task)
{
    task.ContinueWith( t =>
    {
         var aggException = t.Exception.Flatten();
         foreach(var exception in aggException.InnerExceptions)
             LogException(exception);
    }, 
    TaskContinuationOptions.OnlyOnFaulted);
}

Mit den oben genannten Funktionen können Sie verhindern, dass eine Aufgabe die App herunterfährt und protokolliert, und zwar über:

Task.Factory.StartNew( () => 
   { 
       // Do your work...
   }).LogExceptions();

Alternativ können Sie die TaskScheduler.UnobservedTaskException abonnieren und dort bearbeiten.


17
OffVerwenden Sie für zusätzliche Unterhaltung eine statische Stub-Methode in einer Klasse, die als Wort aus vier Buchstaben Ihrer Wahl bezeichnet wird, und verwenden Sie diese Methode für Ihre Sammel-Fortsetzungen. Hilft, die aufgestaute Frustration dieser besonderen Ausnahme zu bekämpfen.
Aaronaught

1
@MonsterMMORPG Ja - Sie müssen die Ausnahme grundsätzlich irgendwo abfangen oder behandeln . Solange Sie irgendwo damit umgehen, wird Ihr Kernproblem verschwinden.
Reed Copsey

1
Ist es nicht möglich, dass die Aufgabe eine Ausnahme auslöst, bevor der Aufruf von ContinueWith erfolgt?
Tim Sylvester

1
@ TimSylvester Das Framework wird es weiterhin durch die Fortsetzung abbilden, auch wenn es "bevor" die Fortsetzung angehängt wird
Reed Copsey

32
Wichtiger Hinweis: Dies ist nur erforderlich für .Net 4.0. Die Ausnahmebehandlung wurde standardmäßig geändert , .net 4.5um nicht reißen die Anwendung herunter . Weitere
Informationen finden Sie unter

43

Sicher; Dies bedeutet, dass a Taskabgeschlossen wurde, nachdem es der Speicherbereinigung überlassen wurde, aber die Aufgabe selbst fehlgeschlagen ist. Es gibt zwei Korrekturen:

  • behandeln die Aufgaben nicht direkt (Verwendung ContinueWith(...)zu unterzeichnen, und überprüfen .IsFaultedund .Exceptionauf die Taskim Parameter)
  • Behandeln Sie das TaskScheduler.UnobservedTaskExceptionEreignis und markieren Sie es als beobachtet (Aufruf e.SetObserved()nach Protokollierung des Fehlers)

4
+1 - Mit einem Zusatz - wenn Ihre Fortsetzung nichts anderes tut als das zu überprüfen IsFaulted, können Sie die OnlyOnFaultedFortsetzung Option verwenden und die manuelle Überprüfung vermeiden ...
Reed Copsey

Eigentlich geschah dies, als ich eine öffentliche statische Funktion innerhalb einer tpl-Aufgabe aufrief. Die Verwendung von try catch würde dieses Problem lösen. Muss ich wirklich eine andere Aufgabe erstellen und warten? danke
MonsterMMORPG

4
+1 für die Erwähnung, dass SetObservedon UnobservedTaskExceptionEventArgsaufgerufen werden muss.
James Webster

-17

Probier diese:

public static void ThrowFirstExceptionIfHappens(this Task task)
{
    task.ContinueWith(t =>
    {
        var aggException = t.Exception.Flatten();
        foreach (var exception in aggException.InnerExceptions)
        {
            throw exception; // throw only first, search for solution
        }
    },
    TaskContinuationOptions.OnlyOnFaulted); // not valid for multi task continuations
}

public static Task CreateHandledTask(Action action) 
{
    Task tsk = Task.Factory.StartNew(action);
    tsk.ThrowFirstExceptionIfHappens();
    return tsk;
}

5
Es ist eins ??? Was meinst du? Können Sie erklären, was Ihre Antwort zu den bisherigen Antworten beiträgt?
Gert Arnold

Sie haben gerade eine neue Aufgabe erstellt, indem Sie fortfahren. Diese schlägt dann fehl und gerät in dieselbe Situation.
Robert Taylor

Diese Lösung scheint etwas kompliziert zu sein. Ich denke, Sie würden die Funktionalität unbeabsichtigt ohne Gewinn verstecken.
Velocitas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.