parellellizing异步调用时如何获得最大出站请求?

通过Fiddler分析下面的代码,我意识到使用Parallel Extensions我可以获得最多2个出站请求:

new string[] { "http://stackoverflow.com", "http://superuser.com", "http://serverfault.com", "http://stackexchange.com" } .AsParallel() .Select(a => HttpWebRequest.Create(a).GetResponse()) .ToArray() ; 

我应该使用什么方法来最大化出站请求的数量?

根据Wireshark,这段代码在我的机器上并行运行所有6个HTTP请求:

 var urls = new string[] { "http://stackoverflow.com", "http://superuser.com", "http://serverfault.com", "http://stackexchange.com", "http://www.howtogeek.com", "http://meta.stackoverflow.com" }; var reqs = urls.Select(HttpWebRequest.Create).ToArray(); var iars = reqs.Select(req => req.BeginGetResponse(null, null)).ToArray(); var rsps = reqs.Select((req, i) => req.EndGetResponse(iars[i])).ToArray(); 

基本上它为每个URL创建一个WebRequest在每个URL上调用BeginGetResponse ,然后使用IAsyncResult为每个URL调用EndGetResponse

该文档指出BeginGetResponse使用托管线程池来发出HTTP请求。

默认情况下,PFX会将该线程数创建为CPU的核心数。 这就是为什么你只有两个请求。 使用PFX中的Task类并通过Task.WaitAll运行它们。 (我希望我的猜测是正确的。)

编辑:示例

 var tasks = servers.Select(Task.Create(() => GetResponseCallHere(...))).ToArray(); Task.WaitAll(tasks); 

ServicePointManager.DefaultConnectionLimit

http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx

在您的情况下,将其设置为4。

请注意,在问题中我使用了BeginGetResponse方法的同步版本。 到目前为止我发现的是,最大化出站请求的唯一方法是使用该方法的异步版本。 但这种方法产生了新的问题,即:

  1. 您必须以两种方法拆分调用者逻辑
  2. 很难跟踪是否所有出站呼叫都已完成。
  3. 处理exception很困难。
  4. 如果要运行的任务数量超过线程池大小,那么上帝知道会发生什么

     new string[] { "http://stackoverflow.com", "http://superuser.com", "http://serverfault.com", "http://stackexchange.com" } .Select(a => HttpWebRequest.Create(a).BeginGetResponse(callback, null)) .ToArray();