System.AggregateException для Task.WaitAll
У меня есть следующий код, который запускает ряд асинхронных задач.
List<TimeoutException> TimeoutExceptions = new List<TimeoutException>();
List<TaskCanceledException> TaskCanceledExceptions = new List<TaskCanceledException>();
List<Exception> Exceptions = new List<Exception>();
List<AggregateException> AggregateExceptions = new List<AggregateException>();
List<Models.Channel.IChannel> channels = new List<Models.Channel.IChannel>();
channels.Add(new Models.Channel.DummyChannelName());
var tasks = new List<Task>();
foreach (Models.Channel.IChannel channel in channels)
{
try
{
var cts = new CancellationTokenSource();
cts.CancelAfter(channel.TimeOut);
tasks.Add(Task.Run(() =>
{
channel.Data = channel.RequestOffers(new Models.Request.AvailabilityRequest()).Result;
if (cts.Token.IsCancellationRequested)
cts.Token.ThrowIfCancellationRequested();
}, cts.Token));
}
catch (TimeoutException t)
{
TimeoutExceptions.Add(t);
}
catch (TaskCanceledException tc)
{
TaskCanceledExceptions.Add(tc);
}
catch (AggregateException ae)
{
AggregateExceptions.Add(ae);
}
catch(Exception ex)
{
Exceptions.Add(ex);
}
}
Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(5));
У меня проблема в том, что если задача отменена из-за тайм-аута, я получаю следующее исключение
<ExceptionMessage>One or more errors occurred.</ExceptionMessage>
<ExceptionType>System.AggregateException</ExceptionType>
Это просто простой случай, когда мне нужен Try Catch вокруг Task.WaitAll, или мой код должен быть структурирован по-другому.
1 ответ
Решение
Если в задаче возникает исключение, оно вызывается в вызывающем потоке, когда вы Wait
для задачи. Если задача успешно создана, все исключения, возникающие внутри задачи, помещаются в AggregateException
и брошен на ожидание.
Для вашего примера это означает, что вы можете удалить блок try/catch внутри цикла и использовать его для переноса Task.WaitAll(...)
после петли.
var tasks = new List<Task>();
foreach (Models.Channel.IChannel channel in channels)
{
Task myTask = Task.Run(...); // create your task here
tasks.Add(myTask);
}
try
{
Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(5));
}
catch
{
// Insert Exception handling logic
}