System.Threading.ThreadPool.SetMaxThreads(50, 50);
File.ReadLines().AsParallel().WithDegreeOfParallelism(100).ForAll((s)->{
/*
some code which is waiting external API call
and do not utilize CPU
*/
});
我的系统中的线程计数从未超过CPU数。 我可以使用PLINQ并为每个CPU获取多个线程吗?
答案 0 :(得分:2)
如果您正在调用外部Web API,则可能达到并发同时连接的限制,该连接设置为2.在应用程序开始时,请执行以下操作:
System.Net.ServicePointManager.DefaultConnectionLimit = 4096;
System.Net.ServicePointManager.Expect100Continue = false;
尝试这有帮助。如果没有,那么您尝试并行化的例程中可能存在其他一些瓶颈。
此外,就像其他响应者所说的那样,ThreadPool根据负载决定启动多少个线程。根据我使用TPL的经验,我发现线程随着时间的推移而增加:应用程序运行的时间越长,负载越重,线程就越多。
答案 1 :(得分:1)
PLINQ使用爬山算法来确定TPL使用的线程池的最佳大小。我认为如果你在你的任务中放了很多I / O,那么看到比cpu计数更多的线程是可爱的。
那就是说,我从未见过比cpu计数更多的线程:)。但也许我从未遇到过正确的情况。
答案 2 :(得分:0)
简短回答:不。
线程数量仅限于.Net Framework运行时。没有开发人员控制来控制TPL(任务并行库)使用的线程数。
修改强>
感谢其他一些反馈:实际上可以 - 但不建议 - 手动控制ThreadPool中的线程数,PLINQ和TPL使用它。
我认为任何并行化问题都需要仔细考虑,并仔细构建和测试。这里有很多细微之处。
答案 3 :(得分:0)
我使用以下代码对此进行了测试:
var lines = Enumerable.Range(0, 200).ToArray();
int currentThreads = 0;
int maxThreads = 0;
object l = new object();
lines.AsParallel().WithDegreeOfParallelism(100).ForAll(
s =>
{
lock (l)
{
currentThreads++;
if (currentThreads > maxThreads)
{
maxThreads = currentThreads;
Console.WriteLine(maxThreads);
}
}
Thread.Sleep(3000);
lock (l)
{
currentThreads--;
}
});
Console.WriteLine();
Console.WriteLine(maxThreads);
基本上,它记录当前正在执行的迭代次数,然后保存遇到的最大值。
结果差异很大,在15到25之间,但它总是远远超过我的计算机所拥有的CPU数量(4)。增加休眠时间会增加并发线程的最大数量。所以看起来这里的限制因素是ThreadPool
:它会慢慢地创建新线程,尤其是当作业相对较快地完成时。
如果要增加使用的线程数,则需要使用SetMinThreads()
(不是SetMaxThreads()
)。如果我将最小值设置为50,则实际使用的线程数约为60。
但是有几十个线程除了等待之外什么都不做,效率非常低,特别是在内存消耗方面。您应该考虑使用异步方法。
答案 4 :(得分:0)
PLINQ不适合这种情况。 我发现下一篇文章对我有用。 http://msdn.microsoft.com/en-us/library/hh228609(v=vs.110).aspx