Parallel.ForEach比预期花费更多时间

3

以下是这个问题的代码:

while (true)
{
    Console.WriteLine("start " + DateTime.Now);
    ParallelOptions options = new ParallelOptions();
    options.MaxDegreeOfParallelism = -1;                
    Parallel.ForEach(hosts, item =>
    {
        using (Ping ping = new Ping())
        {
            PingReply pingReply = ping.Send(item.Value, 2000);  // timeout is 2 secs
            App.dict[item.Key].lastConnectTry = new KeyValuePair<bool, DateTime>((pingReply.Status == IPStatus.Success), DateTime.Now);
        }
    });        
    Console.WriteLine("end " + DateTime.Now);
    Thread.Sleep(15000);
}

然而,当我运行该应用程序时,它提供了略微不同的结果:

start 27.04.2012 10:12:32
end 27.04.2012 10:12:42
// it took 10 seconds
start 27.04.2012 10:12:57
end 27.04.2012 10:13:02
// this took 5 secs
start 27.04.2012 10:13:17
end 27.04.2012 10:13:22
//   5 secs
start 27.04.2012 10:13:37
end 27.04.2012 10:13:42
// 5 secs
start 27.04.2012 10:13:57
end 27.04.2012 10:14:01
start 27.04.2012 10:14:16
end 27.04.2012 10:14:19
start 27.04.2012 10:14:34
end 27.04.2012 10:14:36
start 27.04.2012 10:14:51
end 27.04.2012 10:14:54
start 27.04.2012 10:15:09
end 27.04.2012 10:15:11
start 27.04.2012 10:15:26
end 27.04.2012 10:15:29
start 27.04.2012 10:15:44
end 27.04.2012 10:15:46
start 27.04.2012 10:16:01
end 27.04.2012 10:16:06
start 27.04.2012 10:16:21
end 27.04.2012 10:16:24
start 27.04.2012 10:16:39
end 27.04.2012 10:16:41
start 27.04.2012 10:16:56
end 27.04.2012 10:16:59
start 27.04.2012 10:17:14
end 27.04.2012 10:17:16

看起来启动线程需要一些时间,创建它们,然后并行执行时间将被正确安排。

所以问题是为什么处理所有过程需要超过2秒钟,并且如何通过在处理之前引导线程来避免它?

更新:

此循环位于单独的后台线程中。


3
hosts中有多少个元素?你有多少个核心?“引导”线程是什么意思? - Cameron
主机被22个元素填充。两个内核。“引导”意味着在使用的线程池中创建线程。我对此不是很清楚。 - kseen
2个回答

2

那么我该如何使这个循环始终使用具体数量的线程? - kseen
我不这么认为,你可以限制最大值,但否则ForEach和ThreadPool将尝试调整负载。 - Alexei Levenkov
2
你可以尝试预先增加线程池的大小(ThreadPool.SetMinThreads),如https://dev59.com/UmDVa4cB1Zd3GeqPcVZy所讨论的那样。 - Alexei Levenkov
谢谢,Alexei!预先扩展线程池确实有帮助。Спасибо,Alexei! - kseen

1

你实际上没有通过你的并行选项,看这里:

ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = -1;                
Parallel.ForEach(hosts, options, item => // note options passed through here
      // etc

如果这不够创建,您可以增加线程池:

System.Threading.ThreadPool.SetMinThreads System.Threading.ThreadPool.SetMaxThreads

但请注意,除非您知道您将获得改进,否则我不会碰这个。由于您在任务代码中执行了Ping,这可能是导致每次运行之间变异性的原因。


它会给出相同的结果。最大线程数被设置为巨大值,因此没有任何问题。 - kseen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接