Does Parallel.ForEach Block?

Paul Fryer picture Paul Fryer · Apr 14, 2012 · Viewed 15.3k times · Source

Does the .net function Parallel.ForEach block the calling thread? My guess as to the behavior is one of these:

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

Or perhaps something else is happening, anyone know for sure?

This question came up when implementing this in a logging class:

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

Notice the LogMessage method calls some other logging services. I need that part to return immediately, so it doesn't block the calling thread.


Update: Based on comments from others (we have confirmed the behavior is #1). So I have taken advice to use the Task library and rewritten the loop like this:

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

Answer

Gabe picture Gabe · Apr 14, 2012

Number 1 is correct; Parallel.ForEach does not return until the loop has completed. If you don't want that behavior, you can simply execute your loop as a Task and run it on another thread.