0

I have a task where I form thousands of requests which are later sent to a server. The server returns the response for each request and that response is then dumped to an output file line by line.

The pseudo code goes like this:

//requests contains thousands of requests to be sent to the server
string[] requests = GetRequestsString();


foreach(string request in requests)
{
   string response = MakeWebRequest(request);
   ParseandDump(response);
}

Now, as can be seen the serve is handling my requests one by one. I want to make this entire process fast. The server in question is capable of handling multiple requests at a time. I want to apply multi-threading and send let's say 4 requests to the server at a time and dump the response in same thread.

Can you please give me any pointer to possible approaches.

futurenext110
  • 1,991
  • 6
  • 26
  • 31
  • What about something like this, similar question: http://stackoverflow.com/questions/2960056/trying-to-run-multiple-http-requests-in-parallel-but-being-limited-by-windows – Random IT Guy Feb 05 '13 at 16:16
  • Does order matter when writing out the responses? – mbeckish Feb 05 '13 at 16:20
  • I'd have a look at the thread pools or the task parallel library. This question has a good discussion of both approaches: http://stackoverflow.com/questions/5213695/should-i-use-threadpools-or-task-parallel-library-for-io-bound-operations – GrandMasterFlush Feb 05 '13 at 16:17

3 Answers3

2

You can take advantage of Task from .NET 4.0 and the new toy HttpClient, sample code below is showed how you send requests in parallel, then dump response in the same thread by using ContinueWith:

var httpClient = new HttpClient();
var tasks = requests.Select(r => httpClient.GetStringAsync(r).ContinueWith(t =>
            {
                ParseandDump(t.Result);
            }));

Task uses ThreadPool under the hood, so you don't need to specify how many threads should be used, ThreadPool will manage this for you in optimized way.

cuongle
  • 74,024
  • 28
  • 151
  • 206
1

The easiest way would be to use Parallel.ForEach like this:

string[] requests = GetRequestsString();
Parallel.ForEach(requests, request => ParseandDump(MakeWebRequest(request)));

.NET framework 4.0 or greater is required to use Parallel.

Henrik Karlsson
  • 5,559
  • 4
  • 25
  • 42
0

I think this could be done in a consumer-producer-pattern. You could use a ConcurrentQueue (from the namespace System.Collections.Concurrent) as a shared resource between the many parallel WebRequests and the dumping thread.

The pseudo code would be something like:

var requests = GetRequestsString();
var queue = new ConcurrentQueue<string>();

Task.Factory.StartNew(() => 
{
    Parallel.ForEach(requests , currentRequest =>
    {
        queue.Enqueue(MakeWebRequest(request));
    }
});

Task.Factory.StartNew(() =>
{
    while (true)
    {        
       string response;
       if (queue.TryDequeue(out response))
       {
          ParseandDump(response);
       }

    }
  });

Maybe a BlockingCollection might serve you even better, depending on how you want to go about synchronizing the threads to signal the end of incoming requests.

Mithrandir
  • 24,869
  • 6
  • 50
  • 66
  • You're doing a busywait on the side of the consumer. You'd be *much* better served from using a `BlockingCollection`, since you're not doing the waiting properly on your own. – Servy Feb 05 '13 at 16:45