views:

185

answers:

4

Analysing the code below in action through Fiddler, I realized that using Parallel Extensions I can get at maximum 2 outbound requests:

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

What method should I use to maximize the number of outbound requests?

A: 

ServicePointManager.DefaultConnectionLimit

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

In your case, set it to 4.

No Refunds No Returns
Isn't the persistent connection limit per server?
dtb
I tried it, and it didn't work. What noticed is that if I do not dispose my connections my application will stop when it reaches the number of undisposed connections specified on ServicePointManager.DefaultConnectionLimit
Jader Dias
It didn't work because the default limit is way greater than just 4.
Jader Dias
+2  A: 

By default the PFX creates that number of threads as your CPU number of cores. That why you have only two requests. Use Task class from PFX and run them all thru Task.WaitAll. (I hope my guess is correct.)

EDIT: Example

var tasks = servers.Select(Task.Create(() => GetResponseCallHere(...))).ToArray();
Task.WaitAll(tasks);
Vasiliy Borovyak
Isn't PFX built on `Task`? Do you have a link to docs to confirm that the number of threads is set to the number of processors/cores in PFX?
dtb
The default TaskManagerPolicy is created when a parallel foreach loop started. And here is text from ParallelExtensions_Jun08CTP_Help: "IdealProcessors - Gets the ideal number of processor to use for executing tasks on this TaskManagerPolicy. The default is equal to the actual number of processors on the system."
Vasiliy Borovyak
And here is proof link to PFX forum: http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/5b1383ed-27c1-40ba-8d98-b5ab5aa762ec
Vasiliy Borovyak
"the June 2008 CTP is creating two threads per logical processor"; " this was just a temporary workaround for the CTP release"... @Jader Dias: Are you using the June 2008 CTP?
dtb
I am using .NET Framework 4.0 beta 2 which includes the latest published version of Parallel Fx
Jader Dias
A: 

Note that in the question I used the sychronous version of the BeginGetResponse method. What I have found so far is that the only way to maximize the outbound request is to use the async version of the method. But this approach yields new problems, namely:

  1. You must split your caller logic in two methods
  2. It's difficult to keep track whether all outbound calls were completed.
  3. It's difficult to handle exceptions.
  4. If the number of tasks to run surpasses the thread pool size, then god knows what happens

    new string[] 
    {
        "http://stackoverflow.com",
        "http://superuser.com",
        "http://serverfault.com",
        "http://stackexchange.com"
    }
    .Select(a => HttpWebRequest.Create(a).BeginGetResponse(callback, null))
    .ToArray();
    
Jader Dias
Did you try this without the .AsParallel() ? I would expect little difference.
Henk Holterman
@Henk you're right
Jader Dias
+1  A: 

This code runs all 6 HTTP requests in parallel on my machine according to Wireshark:

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<string, WebRequest>(HttpWebRequest.Create).ToArray();
var iars = reqs.Select(req => req.BeginGetResponse(null, null)).ToArray();
var rsps = reqs.Select((req, i) => req.EndGetResponse(iars[i])).ToArray();

Basically it creates a WebRequest for each URL, calls BeginGetResponse on each and then calls EndGetResponse for each with the IAsyncResult.

The documentation states that BeginGetResponse uses The Managed Thread Pool to make the HTTP request.

dtb
Now that I tested your code I realized that it achieves a maximum of 7 simultaneous requests on my machine (for larger input arrays).
Jader Dias