Пометить исключение задачи как обработанное
Как я могу отметить исключение, брошенное в задачу, как обработанную. Проблема в том, когда я звоню Wait()
метод задачи, он бросит AggregateException
даже когда я уже занимался AggregateException
давным давно. Следующий фрагмент кода показывает проблему, которую я хочу решить. Я мой оригинальный код, я обрабатываю AggregateException
в одной части моего кода, и я называю Wait()
метод в другой части моего кода. Но проблема та же.
static void Main(string[] args)
{
Task task = null;
try
{
task = new Task(() =>
{
Console.WriteLine("Task started");
Thread.Sleep(1000);
throw new InvalidOperationException("my test exception");
});
task.ContinueWith(t =>
{
Console.WriteLine("Task faulted");
AggregateException ae = t.Exception;
ae.Flatten().Handle(ex =>
{
if (typeof(InvalidOperationException) == ex.GetType())
{
Console.WriteLine("InvalidOperationException handled --> " + ex.Message);
return true;
}
return false;
});
}, TaskContinuationOptions.OnlyOnFaulted);
task.Start();
Thread.Sleep(2000);
task.Wait();
}
catch (AggregateException ae)
{
Console.WriteLine("AggregateException thrown again!!! Why???");
ae.Flatten().Handle(ex =>
{
Console.WriteLine(ex.Message);
return true;
});
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("Finished");
Console.Read();
}
Код выше производит следующий вывод:
- Задача запущена
- Задача не выполнена
- InvalidOperationException обработано -> мое тестовое исключение
- AggregateException выдается снова!!! Зачем???
- мое тестовое исключение
- Законченный
1 ответ
Когда ошибочная задача Wait
ред исключение повторно. Было бы ненадежным дизайном, если бы исключение было выброшено только иногда.
Но если вы добавляете продолжение, которое обрабатывает исключение, и вы не хотите, чтобы оно было снова выдано, просто не Wait
эта задача снова. Wait
задание продолжения (которое вы в данный момент не используете). Он завершится только после того, как будет выполнено исходное задание, и, если вам нужен результат, просто продолжите, верните его. Таким образом, исключение будет обработано только один раз:
Task continuation = task.ContinueWith(t =>
{
Console.WriteLine("Task faulted");
AggregateException ae = t.Exception;
ae.Flatten().Handle(ex =>
{
if (typeof(InvalidOperationException) == ex.GetType())
{
Console.WriteLine("InvalidOperationException handled --> " + ex.Message);
return true;
}
return false;
});
}, TaskContinuationOptions.OnlyOnFaulted);
task.Start();
Thread.Sleep(2000);
continuation.Wait();
Примечание: это бросит TaskCanceledException
когда исходное задание не выдает исключение, потому что продолжение отменено (из-за TaskContinuationOptions.OnlyOnFaulted
). Чтобы избежать этого, просто удалите флаг и проверьте, t.IsFaulted
,