Задание. Заблокированные и ненаблюдаемые исключения
Скажем, у меня три задачи: a
, b
и c
. Все три гарантированно генерируют исключение в случайное время между 1 и 5 секундами. Затем я пишу следующий код:
await Task.WhenAny(a, b, c);
В конечном итоге это приведет к исключению из того, что было раньше. Поскольку здесь нет try...catch
, это исключение превратится в какое-то другое место в моем коде.
Что происходит, когда оставшиеся две задачи вызывают исключение? Не являются ли эти незаметные исключения, которые приведут к уничтожению всего процесса? Означает ли это, что единственный способ использования WhenAny
находится внутри блока try...catch
, а затем каким-то образом наблюдать остальные две задачи, прежде чем продолжить?
Последующее наблюдение:. Я бы хотел, чтобы ответ применялся как к .NET 4.5, так и к .NET 4.0 с помощью пакета асинхронного таргетинга (хотя, очевидно, с использованием TaskEx.WhenAny
в этом случае).
Ответы
Ответ 1
Что происходит, когда остальные две задачи вызывают исключение?
Те Task
завершатся в неисправном состоянии.
Не являются ли эти незаметные исключения, которые приведут к уничтожению всего процесса?
Не больше.
В .NET 4.0 Task
деструктор будет проходить его ненаблюдаемое исключение TaskScheduler.UnobservedTaskException
, который бы завершить процесс, если необработанные.
В .NET 4.5 это поведение
Ответ 2
Да, остальные исключения задачи остаются незаметными. Pre.NET 4.5 вы обязаны их соблюдать (не знаете, как ситуация на .NET 4.5, но она изменилась).
Обычно я пишу для себя вспомогательный метод для таких задач, как:
public static void IgnoreUnobservedExceptions(this Task task)
{
if (task.IsCompleted)
{
if (task.IsFaulted)
{
var dummy = task.Exception;
}
return;
}
task.ContinueWith(t =>
{
var dummy = t.Exception;
}, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
}
Возможно, вы захотите включить ведение журнала в производственных приложениях.