我正在使用并行
linq,我正在尝试使用这样的密码下载许多urls:
@H_502_11@解决方法
int threads = 10; Dictionary<string,string> results = urls.AsParallel( threads ).ToDictionary( url => url,url => GetPage( url );@H_404_3@由于下载网页是网络绑定而不是cpu绑定,使用比我的处理器/核心数更多的线程是非常人为的,因为每个线程的大部分时间都花在等待网络的赶上.然而,判断形式的事实是,使用threads = 2运行上面的事实与我的双核机器上的threads = 10具有相同的性能,我认为发送到AsParallel的脚本仅限于核心数量.
有没有办法来重写这个行为?有没有类似的库可用,没有这个限制?
(我已经找到了这样一个python的库,但是需要一些在.Net中使用的东西)
URL是否指向同一个服务器?如果是这样,可能是您正在达到HTTP连接限制而不是线程限制.有一个简单的方法来告诉 – 将您的代码更改为:
int threads = 10; Dictionary<string,string> results = urls.AsParallel(threads) .ToDictionary(url => url,url => { Console.WriteLine("On thread {0}",Thread.CurrentThread.ManagedThreadId); return GetPage(url); });@H_404_3@编辑:嗯我不能让ToDictionary()根据一些示例代码进行并行化.它适用于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; Dictionary<string,string> results = 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; } }@H_404_3@那么这个使用了多少个线程呢?为什么善良知道我有2个处理器,所以不是这样 – 我们已经指定了10个线程,所以不是这样.即使我更改GetPage来敲击cpu仍然使用5.
如果你只需要使用它来处理一个特定的任务 – 而且你不介意稍微有点臭的代码 – 你可能最好不要自己实现,老实说.