2011-10-24 4 views
81

Co to oznacza i jak go rozwiązać?Wyjątki zadania nie zostały zaobserwowane przez oczekiwanie na zadanie lub uzyskanie dostępu do jego właściwości wyjątku. W rezultacie wyjątek nieobsługiwany to

Używam zadań TPL.

Cały błąd

Wyjątek (e) Zadanie nie zaobserwowano ani przez Oczekiwanie na zadanie lub dostępu do jego własności wyjątku. W rezultacie nieobserwowany wyjątek został ponownie zgłoszony przez wątek finalizatora.

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

mscorlib

Odpowiedz

128

Jeśli tworzysz zadanie, a nie zawsze zadzwonić task.Wait() lub próbować odzyskać jego wynik Task<T> , gdy zadanie zostanie zebrane przez odśmiecacz, zerwie twoje podanie podczas finalizacji. Szczegółowe informacje można znaleźć na stronie MSDN pod adresem Exception Handling in the TPL.

Najlepszym rozwiązaniem jest "obsłużyć" wyjątek. Można to zrobić poprzez kontynuację - możesz dołączyć kontynuację do zadania i zalogować/połknąć/etc wyjątek, który występuje. To zapewnia czystą drogę do logowania wyjątki zadanie i może być zapisany jako prostą metodę rozszerzenia, tj:

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); 
} 

Z powyższego można uniknąć zadanie z burząc aplikację i zaloguj się poprzez:

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

Można również subskrybować numer TaskScheduler.UnobservedTaskException i obsługiwać go.

+14

Dla dodana rozrywka, użyj statycznej metody krótkiej "Off" w klasie o nazwie czteroliterowej i wybierz ją dla swoich kontynuacji catch-all. Pomaga zwalczyć niektóre z nagromadzonej frustracji z tego szczególnego wyjątku. – Aaronaught

+0

faktycznie tak się stało, gdy nazwałem publiczną funkcję statyczną wewnątrz zadania tpl. użycie catch-u spróbować rozwiązałoby ten problem? czy naprawdę muszę stworzyć kolejne zadanie i czekać? – MonsterMMORPG

+0

@MonsterMMORPG: Funkcja catch catch wewnątrz funkcji (public static), która wychwyciła wyjątek, poradziłaby sobie z tym. Problem polega na tym, że wyjątek jest "bulgotaniem" do samego zadania, a ty nigdy nie czekasz na wykonanie zadania. Jeśli to zrobisz, naprawi to. –

32

Pewnie; oznacza to, że Task została sfinalizowana po pozostawieniu do czyszczenia pamięci, ale samo zadanie nie powiodło się. Istnieją dwie poprawki:

  • obsłużyć zadania nie bezpośrednio (użyj ContinueWith(...) do subskrybowania i sprawdzić .IsFaulted i .Exception na Task w parametrze)
  • obsłużyć zdarzenia TaskScheduler.UnobservedTaskException i oznaczyć go przestrzegać (wezwanie e.SetObserved() po rejestrowanie błędu)
+3

+1 - Z jednym dodatkiem - jeśli twoja kontynuacja nie robi nic oprócz sprawdzania 'IsFaulted', możesz użyć opcji kontynuacji' OnlyOnFaulted' i uniknąć ręcznego sprawdzenia ... –

+0

faktycznie to się stało, gdy nazwałem publiczną funkcję statyczną wewnątrz zadania tpl. użycie catch-u spróbować rozwiązałoby ten problem? czy naprawdę muszę stworzyć kolejne zadanie i czekać? dziękuje – MonsterMMORPG

+3

+1 za wspomnienie, że 'SetObserved' na' UnobservedTaskExceptionEventArgs' musi zostać wywołany. –

-13

spróbować tego:

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

_Jest jeden _ ??? Co masz na myśli? Czy mógłbyś wyjaśnić, jak twoja odpowiedź przyczynia się do odpowiedzi na razie? –

+0

właśnie utworzyłeś nowe zadanie, kontynuując, które następnie zawiedzie i dostanie się do tej samej sytuacji. –

Powiązane problemy