Как правильно управлять исключением в задаче с помощью ContinueWith
После прочтения информации об управлении задачами и exepcion, я использую этот код для управления исключением, выданным в Задаче:
Task<Object> myTask = Task.Factory.StartNew<Object>(doTask, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
myTask .ContinueWith(task => afterTask(task), TaskScheduler.FromCurrentSynchronizationContext());
Где doTask и AfterTask находятся:
private <Object> doTask() {
throw new Exception("BOOM");
}
private afterTask(Task<Object> aTask) {
if (aTask.IsFaulted)
{
MessageBox.Show(aTask.Exception.InnerException.Message);
}
else //whatever
}
Когда генерируется Exception Boom, Visual Studio отображает предупреждение, информирующее о том, что исключение не было перехвачено, но если я продолжу выполнение, исключение будет обработано в функции afterTask.
Правильно ли этот код или я неправильно понял какое-то основное поведение задачи? Есть ли способ избежать предупреждения отладчика о том, что выполнение не было поймано? Это немного раздражает...
заранее спасибо
2 ответа
Попробуйте это вместо этого:
task.ContinueWith(
t =>
t.Exception.Handle(ex =>
{
logger.Error(ex.Message, ex);
return false;
})
, TaskContinuationOptions.OnlyOnFaulted
);
Используя TaskContinuationOptions.OnlyOnFaulted
запускаешь ContinueWith
блокировать только если исключение выдается исходной задачей.
Кроме того, вы можете выбрать, возвращать ли true или false из лямбда-выражения, переданного Handle
, указывающий, было ли обработано исключение или нет. В моем случае я не хотел, чтобы исключение распространялось. Вы можете изменить его, чтобы вернуть true
в твоем случае.
try
{
var t1 = Task.Delay(1000);
var t2 = t1.ContinueWith(t =>
{
Console.WriteLine("task 2");
throw new Exception("task 2 error");
}, TaskContinuationOptions.OnlyOnRanToCompletion);
var t3 = t2.ContinueWith(_ =>
{
Console.WriteLine("task 3");
return Task.Delay(1000);
}, TaskContinuationOptions.OnlyOnRanToCompletion).Unwrap();
// The key is to await for ALL tasks rather than just
// the first or last task.
await Task.WhenAll(t1, t2, t3);
}
catch (AggregateException aex)
{
aex.Flatten().Handle(ex =>
{
// handle your exceptions here
Console.WriteLine(ex.Message);
return true;
});
}