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()少なくとも 1 つの Task インスタンスが取り消されたAggregateException場合、または少なくとも 1 つの Task インスタンスの実行中に例外がスローされた場合にスローされます。

ContinueWhenAll()この例外はスローされず、すべてがキャンセルされたかどうかなどで最後のタスクが開始されます。

于 2011-08-10T08:41:09.087 に答える
2

List<T>まず、スレッド セーフではないwithを使用していることに気付きました。Parallel.ForEachこれを並行コレクションに置き換える必要がありますConcurrentQueue<T>

WaitAllvsに関してはContinueWhenAllWaitAllタスクのいずれかに障害が発生した場合にスローされるため、上記のコードはすべてのタスクが正常に完了したことを検証するためのものです。ContinuationOptionsパラメータをContinueWhenAlllikeに渡すと同じことができるためOnlyRanToCompeletion、すべてのタスクが完了した場合にのみ継続タスクがスケジュールされます。成功しました。

于 2011-08-12T08:09:43.143 に答える