5

我正在努力将线程合并到我的 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 提供的文档)。等待您已经知道已经完成的线程似乎有点奇怪,对吗?我能想象的唯一原因是冒泡错误并处理这些错误。我在这里错过了什么吗?

4

2 回答 2

4

Task.WaitAll()AggregateException当至少一个 Task 实例被取消时,将抛出一个异常 - 或者 - 在至少一个 Task 实例的执行期间抛出异常。

ContinueWhenAll()不会抛出这个异常,它只是在一切完成取消或不取消等时开始你的最后一个任务。

于 2011-08-10T08:41:09.087 回答
2

首先,我注意到您使用List<T>Parallel.ForEach不是线程安全的,您应该将其替换为并发集合,例如:ConcurrentQueue<T>.

关于WaitAllvs ContinueWhenAllWaitAll如果任何一个任务出错都会抛出,所以上面的代码是为了验证所有任务是否成功完成,如果你传递ContinuationOptions参数给ContinueWhenAlllike也可以这样做,OnlyRanToCompeletion这样只有在所有任务完成后才会安排继续任务成功地。

于 2011-08-12T08:09:43.143 回答