.net関数 Parallel.ForEach は呼び出しスレッドをブロックしますか?行動に関する私の推測はこれらの1つです。
それとも何か他のことが起こっているのでしょうか?
この質問は、ロギングクラスでこれを実装するときに発生しました。
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));
番号1は正しいです。 Parallel.ForEach
は、ループが完了するまで戻りません。その動作を望まない場合は、ループをTask
として実行し、別のスレッドで実行できます。
通常のforeach()でStartNewを更新します。
これは大規模なコレクションには最適ではない可能性があり、エラーを処理するポイントがありません。
あなたのloggingServicesはおそらく何千ものアイテムを保持していませんが、エラー処理はポイントのままです。
検討してください:
Task.Factory.StartNew(() =>
{
try
{
Parallel.ForEach(loggingServices, l => l.LogMessage(request));
}
catch(SomeException ex)
{
// at least try to log it ...
}
});