Task.Wait в ContinueWhen Все действия - PullRequest
5 голосов
/ 10 августа 2011

Я работал над объединением потоков в свой код 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 ]

4 голосов
/ 10 августа 2011

Task.WaitAll() сгенерирует AggregateException, когда хотя бы один из экземпляров Задачи был отменен - ​​или - возникла исключительная ситуация во время выполнения хотя бы одного из Экземпляры задач.

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

2 голосов
/ 12 августа 2011

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

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

...