Le eccezioni di un'attività non sono state osservate né da Waiting on the Task né accedendo alla sua proprietà Exception. Di conseguenza, l'eccezione inosservata è stata


100

Cosa significa e come risolverlo?

Sto usando attività TPL.

L'intero errore

Le eccezioni di un'attività non sono state osservate né da Waiting on the Task né accedendo alla sua proprietà Exception. Di conseguenza, l'eccezione non osservata è stata lanciata di nuovo dal thread del finalizzatore.

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

mscorlib

Risposte:


158

Se crei un'attività e non chiami task.Wait()o non provi mai a recuperare il risultato di a Task<T>, quando l'attività viene raccolta dal garbage collector, verrà interrotta l'applicazione durante la finalizzazione. Per i dettagli, vedere la pagina di MSDN sulla gestione delle eccezioni nel TPL .

L'opzione migliore qui è "gestire" l'eccezione. Questo può essere fatto tramite una continuazione: è possibile allegare una continuazione all'attività e registrare / ingoiare / ecc. L'eccezione che si verifica. Questo fornisce un modo pulito per registrare le eccezioni delle attività e può essere scritto come un semplice metodo di estensione, ad esempio:

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

Con quanto sopra, puoi impedire a qualsiasi attività di abbattere l'app e di registrarla tramite:

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

In alternativa, puoi iscriverti a TaskScheduler.UnobservedTaskException e gestirlo lì.


17
Per un maggiore divertimento, disponi di un metodo stub statico Offin una classe denominata come parola di quattro lettere di tua scelta e usalo per le tue continuazioni catch-all. Aiuta a combattere alcune delle frustrazioni represse derivanti da questa particolare eccezione.
Aaronaught

1
@MonsterMMORPG Sì - Fondamentalmente devi catturare o gestire l'eccezione da qualche parte . Finché lo gestisci da qualche parte, il tuo problema principale scomparirà.
Reed Copsey

1
Non è possibile che l'attività possa generare un'eccezione prima che venga effettuata la chiamata a ContinueWith?
Tim Sylvester

1
@TimSylvester Il framework lo mapperà ancora attraverso la continuazione, anche se accade "prima" che la continuazione sia allegata
Reed Copsey

32
Nota importante: è necessario solo per .Net 4.0. La gestione delle eccezioni è stata modificata per impostazione predefinita in modo .net 4.5da non distruggere l'applicazione . Ulteriori informazioni in Gestione delle eccezioni delle attività in .NET 4.5
i3arnon

43

Sicuro; significa che è Taskstato finalizzato dopo essere stato lasciato alla raccolta dei rifiuti, ma l'attività stessa non è riuscita. Ci sono due soluzioni:

  • gestire le attività non riescono direttamente (uso ContinueWith(...)a sottoscrivere, e controllare .IsFaultede .Exceptionsul Tasknel parametro)
  • gestire l' TaskScheduler.UnobservedTaskExceptionevento e contrassegnarlo come osservato (chiamare e.SetObserved()dopo aver registrato l'errore)

4
+1 - Con un'aggiunta - se la tua continuazione non fa altro che spuntare IsFaulted, puoi usare l' OnlyOnFaultedopzione di continuazione ed evitare il controllo manuale ...
Reed Copsey

in realtà questo è successo quando ho chiamato una funzione statica pubblica all'interno di un'attività tpl. utilizzando try catch risolverebbe questo problema? devo davvero creare un'altra attività e aspettare? grazie
MonsterMMORPG

4
+1 Per menzionare che SetObservedil UnobservedTaskExceptionEventArgsdeve essere chiamato.
James Webster,

-17

Prova questo:

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
È uno ??? Cosa intendi? Potresti spiegare in che modo la tua risposta contribuisce alle risposte finora?
Gert Arnold

hai appena creato una nuova attività continuando che poi fallirà e ti ritroverai nella stessa situazione.
Robert Taylor

Questa soluzione sembra un po 'complicata. Penso che nasconderesti la funzionalità involontariamente senza alcun guadagno.
Velocitas
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.