System.AggregateException для Task.WaitAll - PullRequest
0 голосов
/ 13 января 2019

У меня есть следующий код, который запускает ряд асинхронных задач.

        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 Ответ

0 голосов
/ 13 января 2019

Если в задаче возникает исключение, оно вызывается в вызывающем потоке, когда вы 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
}
...