Parallel.ForEach块吗?

.net函数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方法调用一些其他日志logging服务。 我需要这部分立即返回,所以它不会阻止调用线程。


更新:根据别人的评论(我们已经确认行为是#1)。 所以我build议使用任务库,并重写这样的循环:

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

1号是正确的; 在循环完成之前, Parallel.ForEach不会返回。 如果你不想要这样的行为,你可以简单地将你的循环作为一个Task执行,并在另一个线程上运行它。

重新你的更新,在一个正常的foreach()中的StartNew:

这可能不是大集合的最佳select,而且您也无法处理错误。

您的loggingServices可能不包含数千个项目,但error handling仍然是一个重点。

考虑:

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