Task.Wait в ContinueWhenAll Action
Я работал над объединением потоков в свой код Azure для помещения вещей в очередь. Для этого я использовал http://www.microsoft.com/download/en/details.aspx?id=19222 в качестве справочного материала.
мой код для постановки в очередь нескольких сообщений выглядит так:
public void AddMessagesAsync(IEnumerable<IQueueMessage> messages, string queue = null, TimeSpan? timeToLive = null)
{
//check if we need to switch queues
if (!String.IsNullOrEmpty(queue))
{
SetCurrent(queue);
}
//setup list of messages to enqueue
var tasks = new List<Task>();
Parallel.ForEach(messages, current => {
if (timeToLive.HasValue)
{
//create task with TPL
var task = Task.Factory.FromAsync(Current.BeginAddMessage, Current.EndAddMessage, Convert(current), timeToLive.Value, tasks);
//setup continuation to trigger eventhandler
tasks.Add(task.ContinueWith((t) => AddMessageCompleted(t)));
}
else
{
//create task with TPL
var task = Task.Factory.FromAsync(Current.BeginAddMessage, Current.EndAddMessage, Convert(current), tasks);
//setup continuation to trigger eventhandler
tasks.Add(task.ContinueWith((t) => AddMessageCompleted(t)));
}
});
//setup handler to trigger when all messages are enqueued, a we are blocking the thread over there to wait for all the threads to complete
Task.Factory.ContinueWhenAll(tasks.ToArray(), (t) => AddMessagesCompleted(t));
}
private void AddMessagesCompleted(Task[] tasks)
{
try
{
//wait for all tasks to complete
Task.WaitAll(tasks);
}
catch (AggregateException e)
{
//log the exception
var ex = e;
//return ex;
}
if (AddedMessages != null)
{
AddedMessages(tasks, EventArgs.Empty);
}
}
Теперь мой вопрос о Task.Wait в продолжении (что соответствует документу, предоставленному MS). кажется немного странным ждать потоков, где вы уже знаете, что закончили правильно? единственная причина, которую я могу себе представить, - это всплыть и обработать ошибки. я что-то здесь упускаю?
2 ответа
Task.WaitAll()
бросит AggregateException
когда по крайней мере один из экземпляров Задачи был отменен или возникла исключительная ситуация во время выполнения хотя бы одного экземпляра Задачи.
ContinueWhenAll()
не будет выбрасывать это исключение, и оно просто запустит вашу последнюю задачу, когда все закончится, отменено или нет и т. д.
Во-первых, я заметил, что вы используете List<T>
с Parallel.ForEach
который не является потокобезопасным, вы должны заменить его на параллельную коллекцию, например: ConcurrentQueue<T>
,
относительно WaitAll
против ContinueWhenAll
, WaitAll
сгенерирует, если какая-либо из задач будет с ошибкой, поэтому приведенный выше код предназначен для проверки успешного завершения всех задач, вы можете сделать то же самое, если передадите ContinuationOptions
параметр для ContinueWhenAll
лайк OnlyRanToCompeletion
поэтому задача продолжения будет запланирована только в том случае, если все задачи выполнены успешно.