2012-04-14 2 views
39

.net関数Parallel.ForEachが呼び出しスレッドをブロックしていますか?行動に関する私の推測は、次のいずれかです:Parallel.ForEachはブロックしますか?

  1. はい、最も遅いアイテムが実行されるまでブロックされます。
  2. いいえ、ブロックしないでコントロールをすぐに返します。並行して実行される項目は、バックグラウンドスレッドで実行されます。

おそらく、誰かが確実に知っていることはありますか?ログクラスでこれを実装するとき

この質問は、思い付いた:

public class MultipleLoggingService : LoggingServiceBase 
{ 
    private readonly List<LoggingServiceBase> loggingServices; 

    public MultipleLoggingService(List<LoggingServiceBase> loggingServices) 
    { 
     this.loggingServices = loggingServices; 
     LogLevelChanged += OnLogLevelChanged; 
    } 

    private void OnLogLevelChanged(object sender, LogLevelChangedArgs args) 
    { 
     loggingServices.ForEach(l => l.LogLevel = LogLevel); 
    } 

    public override LogMessageResponse LogMessage(LogMessageRequest request) 
    { 
     if (request.LogMessage) 
      Parallel.ForEach(loggingServices, l => l.LogMessage(request)); 

     return new LogMessageResponse{MessageLogged = request.LogMessage}; 
    } 
} 

LogMessage方法は、いくつかの他のロギングサービスを呼び出して注意してください。私はその部分をすぐに返す必要があるので、呼び出しスレッドをブロックしません。


更新:他の人のコメントに基づいています(動作は#1であることが確認されています)。だから私はTaskライブラリを使用するようにアドバイスを取り、このようなループを書き換えています

  if (request.LogMessage) 
      foreach (var loggingService in loggingServices) 
       Task.Factory.StartNew(() => loggingService.LogMessage(request)); 

答えて

48

ナンバー1は正しいです。 Parallel.ForEachはループが完了するまで戻りません。その動作を望まない場合は、単にループをTaskとして実行し、別のスレッドで実行するだけです。通常のforeachの(にご更新、StartNew)再

+0

感謝を!このコンテキストで「タスク」を使用する方法について少しコードスニペットがありますか?ありがとう、ポール –

+1

@PaulFryer: 'タスクt = Task.TaskFactory.StartNew(()=> {/ * Parallel.For行く* /}); ' – Richard

+6

技術的には、呼び出し元スレッドは並列ループで使用されます。つまり、ループをブロックするだけではなく、ワーカースレッドの1つとして使用されます。 –

8

は:

これは、大規模なコレクションのために最適ではないかもしれない、とあなたはエラーを処理するためのポイントを得ることはありません。

ロギングサービスには何千ものアイテムが格納されていない可能性がありますが、エラー処理は重要なポイントです。

は考えてみましょう:先端のための

Task.Factory.StartNew(() => 
{ 
    try 
    { 
     Parallel.ForEach(loggingServices, l => l.LogMessage(request)); 
    } 
    catch(SomeException ex) 
    { 
     // at least try to log it ... 
    } 
}); 
+0

ああ、良い点。私は、ロギングサービスが失敗した場合、エラーをログに記録する方法について少し考えてみる必要があります:-) –

関連する問題