4

我需要从网站上抓取数据。我有超过 1,000 个需要访问的链接,以前我将每个线程划分为 10 个链接,并且将启动 100 个线程,每个线程拉出 10 个。在几个测试用例之后,100 个线程是最小化检索内容时间的最佳计数所有的链接。

我意识到 .NET 4.0 为开箱即用的多线程提供了更好的支持,但这是根据您拥有的内核数量来完成的,在我的情况下,这并没有产生足够的线程。我想我要问的是:优化 1,000 链接拉动的最佳方法是什么。我应该使用.ForEach并让Parallel扩展程序控制产生的线程数量,还是找到一种方法来告诉它启动和划分工作的线程数?

我以前没有合作过,Parallel所以也许我的方法可能是错误的。

4

4 回答 4

5

您可以使用Parallel.ForEach 中的MaxDegreeOfParallelism 属性来控制将产生的线程数。

这是代码片段 -

ParallelOptions opt = new ParallelOptions();
opt.MaxDegreeOfParallelism = 5;

Parallel.ForEach(Directory.GetDirectories(Constants.RootFolder), opt, MyMethod);
于 2013-10-18T09:13:23.310 回答
4

一般来说,Parallel.ForEach()在优化线程数方面是相当不错的。它考虑了系统中的内核数量,但也考虑了线程在做什么(CPU 绑定、IO 绑定、方法运行多长时间等)。

您可以控制最大并行化程度,但没有强制使用更多线程的机制。

确保您的基准是正确的,并且可以以公平的方式进行比较(例如,相同的网站,在开始测量之前允许一个热身期,并进行多次运行,因为响应时间差异可能是相当高的抓取网站)。如果经过仔细测量,您自己的线程代码仍然更快,您可以得出结论,您针对特定情况进行了比 .NET 更好的优化并坚持使用您自己的代码。

于 2013-02-08T16:53:45.877 回答
3

值得一试的是 TPL Dataflow 库。

MSDN上的数据流。

请参阅Parallel.ForEach 中的嵌套等待

Parallel.ForEach() 背后的整个想法是你有一组线程,每个线程处理集合的一部分。正如您所注意到的,这不适用于 async-await,您希望在异步调用期间释放线程。

此外,演练创建数据流管道专门设置和处理多个网页下载。TPL 数据流确实是为这种情况而设计的。

于 2013-02-08T17:04:16.387 回答
0

如果不查看您的代码以及集合是如何定义的,很难说,我发现这 Parallel.Invoke是最灵活的。试试msdn?...听起来你正在寻找使用Parallel.For Method (Int32, Int32, Action<Int32, ParallelLoopState>)

于 2013-02-08T16:59:30.233 回答