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

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

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

Вся ошибка

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

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

mscorlib

Ответы [ 3 ]

149 голосов
/ 25 октября 2011

Если вы создаете задание, и вы никогда не вызываете 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 и обработать его там.

40 голосов
/ 25 октября 2011

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

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

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

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