c# startnew Le eccezioni di un'attività non sono state osservate in Attesa sull'attività o accedendo alla relativa proprietà di eccezione. Di conseguenza, l'eccezione non osservata era




c# task new (3)

Cosa significa e come risolverlo?

Sto usando attività TPL.

L'intero errore

Le eccezioni di un'attività non sono state osservate in Attesa sull'attività o accedendo alla relativa proprietà di eccezione. Di conseguenza, l'eccezione non osservata è stata rimandata dal thread del finalizzatore.

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

mscorlib


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

L'opzione migliore qui è "gestire" l'eccezione. Ciò può essere fatto tramite una continuazione: è possibile allegare una continuazione all'attività e registrare / ingoiare / ecc. L'eccezione che si verifica. Ciò 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 demolire l'app e registrarla, tramite:

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

In alternativa, è possibile abbonarsi a TaskScheduler.UnobservedTaskException e gestirlo lì.


Sicuro; significa che un'attività è stata finalizzata dopo essere stata lasciata alla raccolta dati inutili, ma l'attività in sé non è riuscita. Ci sono due correzioni:

  • gestire le attività fallite direttamente (usare ContinueWith(...) per iscriversi e controllare. .IsFaulted e .Exception nel parametro)
  • gestire l'evento TaskScheduler.UnobservedTaskException e contrassegnarlo come osservato (chiamare e.SetObserved() dopo aver registrato l'errore)

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




task-parallel-library