Исключение (я) Задачи не было обнаружено ни Ожиданием Задачи, ни доступом к ее свойству Исключение. В результате ненаблюдаемое исключение было
Что это значит и как решить?
Я использую задачи 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;
}