【问题标题】:Does Parallel.ForEach Block?Parallel.ForEach 会阻塞吗?
【发布时间】:2012-04-14 12:44:34
【问题描述】:

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


更新:基于其他人的 cmets(我们已确认行为是 #1)。所以我接受了使用Task 库的建议,并像这样重写了循环:

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

【问题讨论】:

    标签: c# .net multithreading logging parallel-processing


    【解决方案1】:

    数字 1 是正确的; Parallel.ForEach 在循环完成之前不会返回。如果您不希望这种行为,您可以简单地将循环作为Task 执行并在另一个线程上运行。

    【讨论】:

    • 感谢您的提示!您是否碰巧有一些关于如何在这种情况下使用“任务”的代码 sn-p?谢谢,保罗
    • @PaulFryer: Task t = Task.TaskFactory.StartNew(() =&gt; {/* Parallel.For goes here */});
    • 从技术上讲,调用线程用于并行循环。所以它不是“浪费”只是阻塞循环 - 它被用作工作线程之一。
    【解决方案2】:

    你的更新,StartNew 在一个普通的 foreach() 中:

    这可能不是大型集合的最佳选择,而且您没有处理错误的意义。

    您的 loggingServices 可能不包含数千个项目,但错误处理仍然很重要。

    考虑:

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

    【讨论】:

    • 啊,好点子。我得考虑一下,如果日志服务失败,如何记录错误:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多