Исключение (я) Задачи не было обнаружено ни Ожиданием Задачи, ни доступом к ее свойству Исключение. В результате ненаблюдаемое исключение было

Что это значит и как решить?

Я использую задачи TPL.

Вся ошибка

Исключение (я) Задачи не было обнаружено ни Ожиданием Задачи, ни доступом к ее свойству Исключение. В результате ненаблюдаемое исключение было переброшено потоком финализатора.

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

mscorlib

3 ответа

Решение

Если вы создаете задание, и вы никогда не звоните task.Wait() или попробуйте получить результат Task<T>Когда задача будет собрана сборщиком мусора, она завершит работу вашего приложения во время финализации. Для получения дополнительной информации см. Страницу MSDN по обработке исключений в TPL.

Лучший вариант здесь - "обработать" исключение. Это можно сделать с помощью продолжения - вы можете прикрепить продолжение к задаче и зарегистрировать / проглотить / и т.д. возникшее исключение. Это обеспечивает чистый способ регистрации исключений задач и может быть записан как простой метод расширения, а именно:

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

С помощью вышеизложенного вы можете предотвратить любую задачу, которая может привести к срыву приложения и регистрации его с помощью:

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

Кроме того, вы можете подписаться на TaskScheduler.UnobservedTaskException и обработать его там.

Конечно; это означает Task был завершен после того, как был оставлен для сборки мусора, но сама задача не удалась. Есть два исправления:

  • обрабатывать задачи терпеть неудачу напрямую (использовать ContinueWith(...) подписаться и проверить .IsFaulted а также .Exception на Task в параметре)
  • обращаться с TaskScheduler.UnobservedTaskException событие, и отметьте это как наблюдаемое e.SetObserved() после регистрации ошибки)

Попробуй это:

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;
}
Другие вопросы по тегам