Задача.Ожидание в действии ContinueWhenAll
Я работал над инкорпорированием потоков в мой код 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);
}
}
Теперь мой вопрос касается задачи.Подождите в продолжении (что соответствует документу, предоставленному MS). кажется немного странным ждать потоков, где вы уже знаете, что завершили правильно? единственный причина, которую я могу себе представить, состоит в том, чтобы пузырить ошибки и обрабатывать их. я что-то упустил?2 ответа:
Task.WaitAll()бросит АНAggregateExceptionесли хотя бы один из экземпляров задачи был отменен-или - исключение было выдано во время выполнения хотя бы одного из экземпляров задачи.
ContinueWhenAll()не будет бросать это исключение и его просто начать свою последнюю задачу, когда все заканчивается отменено или нет и т.д.
Во-первых, я заметил, что вы используете
List<T>сParallel.ForEach, который не является потокобезопасным, вы должны заменить его параллельной коллекцией, например:ConcurrentQueue<T>.Относительно
WaitAllvsContinueWhenAll,WaitAllЕсли какая-либо из задач будет сброшена, поэтому приведенный выше код должен подтвердить, что все задачи успешно завершены, вы можете сделать то же самое, если передадите параметрContinuationOptionsвContinueWhenAll, напримерOnlyRanToCompeletion, поэтому задача продолжения будет запланирована только в том случае, если все задачи завершены успешно.