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 поэтому задача продолжения будет запланирована только в том случае, если все задачи выполнены успешно.

Другие вопросы по тегам