我正在使用并行linq,我正在尝试使用这样的必要代码同时下载许多url:
int threads = 10; Dictionaryresults = urls.AsParallel( threads ).ToDictionary( url => url, url => GetPage( url );
由于下载网页是网络绑定而不是CPU绑定,因此使用比我的处理器/内核数量更多的线程是非常有益的,因为每个线程中的大部分时间都花在等待网络赶上.但是,从我的双核机器上运行上面的thread = 2与thread = 10相同的事实判断,我认为发送到AsParallel的踏板仅限于核心数量.
有没有办法覆盖这种行为?是否有类似的库没有此限制?
(我已经为python找到了这样的库,但需要在.Net中运行的东西)
URL是否指向同一台服务器?如果是这样,可能是您正在达到HTTP连接限制而不是线程限制.有一种简单的方法可以告诉您 - 将代码更改为:
int threads = 10; Dictionaryresults = urls.AsParallel(threads) .ToDictionary(url => url, url => { Console.WriteLine("On thread {0}", Thread.CurrentThread.ManagedThreadId); return GetPage(url); });
编辑:嗯.我不能ToDictionary()
给parallelise 都带着几分的示例代码.它工作正常Select(url => GetPage(url))
但不是ToDictionary
.会搜索一下.
编辑:好的,我仍然无法ToDictionary
进行并行化,但你可以解决这个问题.这是一个简短但完整的程序:
using System; using System.Collections.Generic; using System.Threading; using System.Linq; using System.Linq.Parallel; public class Test { static void Main() { var urls = Enumerable.Range(0, 100).Select(i => i.ToString()); int threads = 10; Dictionaryresults = urls.AsParallel(threads) .Select(url => new { Url=url, Page=GetPage(url) }) .ToDictionary(x => x.Url, x => x.Page); } static string GetPage(string x) { Console.WriteLine("On thread {0} getting {1}", Thread.CurrentThread.ManagedThreadId, x); Thread.Sleep(2000); return x; } }
那么,这使用了多少线程?为什么?善良知道.我有2个处理器,所以不是这样 - 我们已经指定了10个线程,所以不是这样.即使我改变GetPage
锤击CPU,它仍然使用5 .
如果你只需要将它用于一个特定的任务 - 并且你不介意稍微有点臭的代码 - 你可能最好自己实现它,说实话.
默认情况下,.Net具有到端服务点(IP:端口)的2个并发连接的限制.这就是为什么如果所有网址都是同一台服务器你就不会看到差异的原因.
它可以使用ServicePointManager.DefaultPersistentConnectionLimit属性进行控制.