Блокирует ли Parallel.ForEach?

Работает ли .netParallel.ForEach заблокировать вызывающий поток? Мое предположение относительно поведения является одним из них:

Yes, it blocks until the slowest item executing returns. No, it doesn't block and returns control immediately. The items to run in parallel are done on background threads.

Или, может быть, что-то еще происходит, кто-нибудь знает наверняка?

Этот вопрос возник при реализации этого в классе журналирования:

<code>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};
    }
}
</code>

Обратите внимание наLogMessage Метод вызывает некоторые другие службы регистрации. Мне нужно, чтобы эта часть вернулась немедленно, чтобы она не блокировала вызывающий поток.

Обновление: на основе комментариев от других (мы подтвердили, что поведение # 1). Поэтому я принял совет, чтобы использоватьзадача библиотека и переписать цикл следующим образом:

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

Ответы на вопрос(2)

Это может быть не самым оптимальным для больших коллекций, и у вас нет смысла обрабатывать ошибки.

Ваши сервисы loggingServices, вероятно, не содержат тысячи элементов, но обработка ошибок остается точкой.

Рассматривать:

Task.Factory.StartNew(() => 
{
   try
   {
        Parallel.ForEach(loggingServices, l => l.LogMessage(request));
   }
   catch(SomeException ex)
   {
       // at least try to log it ...
   }
});
 Paul Fryer14 апр. 2012 г., 16:02
Ах, хорошая мысль. Мне придется немного подумать об этом, если служба регистрации не работает, как зарегистрировать ошибку :-)
Решение Вопроса

Parallel.ForEach не возвращается, пока цикл не завершится. Если вы не хотите такого поведения, вы можете просто выполнить свой цикл какTask и запустить его в другом потоке.

 Paul Fryer14 апр. 2012 г., 14:57
Спасибо за чаевые! У вас есть небольшой фрагмент кода о том, как использовать & apos; Task & apos; в данном контексте? Спасибо пол
 29 июн. 2012 г., 16:10
Технически вызывающий поток используется в параллельном цикле. Так что это не "впустую" просто блокирование цикла - он используется в качестве одного из рабочих потоков.
 14 апр. 2012 г., 15:50
@PaulFryer:Task t = Task.TaskFactory.StartNew(() => {/* Parallel.For goes here */});

Ваш ответ на вопрос