Задача.Ожидание в действии 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 5

2 ответа:

Task.WaitAll() бросит АН AggregateException если хотя бы один из экземпляров задачи был отменен-или - исключение было выдано во время выполнения хотя бы одного из экземпляров задачи.

ContinueWhenAll() не будет бросать это исключение и его просто начать свою последнюю задачу, когда все заканчивается отменено или нет и т.д.

Во-первых, я заметил, что вы используете List<T> с Parallel.ForEach, который не является потокобезопасным, вы должны заменить его параллельной коллекцией, например: ConcurrentQueue<T>.

Относительно WaitAll vs ContinueWhenAll, WaitAll Если какая-либо из задач будет сброшена, поэтому приведенный выше код должен подтвердить, что все задачи успешно завершены, вы можете сделать то же самое, если передадите параметр ContinuationOptions в ContinueWhenAll, например OnlyRanToCompeletion, поэтому задача продолжения будет запланирована только в том случае, если все задачи завершены успешно.