HttpWebRequest.BeginGetRequestStream() best practice

11,535

Solution 1

You could passing a delegate (as part of the async "state" parameter) that needs to be called. Then after your EndGetResponseStream do what you need and then call this delegate with any parameters you need.

Personally, since you're moving to the aysnc programming model (I assume to get better performance) I strongly suggest you move your workflow over to to asynchronous as well. This model allows you to process the results as they come in and as fast as possible without any blocking whatsoever.

Edit

On my blog there is an article

HttpWebRequest - Asynchronous Programming Model/Task.Factory.FromAsyc

on this subject. I'm currently in the process of writing it, but I've presented a class that I think you could use in your situation. Take a look at either the GetAsync method or PostAsync method depending on what you need.

public static void GetAsyncTask(string url, Action<HttpWebRequestCallbackState> responseCallback,
  string contentType = "application/x-www-form-urlencoded")

Notice the responseCallback parameter? Well that's the delegate I talked about earlier.

Here is an example of how you'd call it (I'm showing the PostAsyn() method

    var iterations = 100;
    for (int i = 0; i < iterations; i++)
    {
      var postParameters = new NameValueCollection();
      postParameters.Add("data", i.ToString());
      HttpSocket.PostAsync(url, postParameters, callbackState =>
        {
          if (callbackState.Exception != null)
            throw callbackState.Exception;
          Console.WriteLine(HttpSocket.GetResponseText(callbackState.ResponseStream));
        });
    }

The loop could be your collection of urls. In the case of a GET you don't need to send any (POST) parameters and the callback is the lambda you see where I'm writing to the console. Here you could do what you need, of you could send in a delegate so the response processing is done "elsewhere".

Also the callback method is an

Action<HttpWebRequestCallbackState>

Where HttpWebRequestCallbackState is a custom class you can modify to include any information you need for your purposes. Or you could modify the signature to to an Action.

Solution 2

The following code I just copy/pasted (and edited) from this article about asynchronous Web requests. It shows a basic pattern of how you can write asynchronous code in a somewhat organized fashion, while keeping track of what responses go with what requests, etc. When you're finished with the response, just fire an event that notifies the UI that a response finished.

private void ScanSites ()
{
  // for each URL in the collection...
  WebRequest request = HttpWebRequest.Create(uri);

  // RequestState is a custom class to pass info
  RequestState state = new RequestState(request, data);

  IAsyncResult result = request.BeginGetResponse(
    new AsyncCallback(UpdateItem),state);
}

private void UpdateItem (IAsyncResult result)
{
  // grab the custom state object
  RequestState state = (RequestState)result.AsyncState;
  WebRequest request = (WebRequest)state.request;
  // get the Response
  HttpWebResponse response =
    (HttpWebResponse )request.EndGetResponse(result);

  // fire the event that notifies the UI that data has been retrieved...
}

Note you can replace the RequestState object with any sort of object you want that will help you keep track of things.

You are probably already doing this, but if not, I believe this is a perfectly acceptable and clean way to tackle the problem. If this isn't what you were looking for, let me know.

Solution 3

You can use the System.Net.WebClient class:

var client = new WebClient();
client.DownloadDataCompleted += (s, args) => { /* do stuff here */ };
client.DownloadDataAsync(new Uri("http://someuri.com/"));
Share:
11,535
joe_coolish
Author by

joe_coolish

Computer Science major at Brigham Young University. Program in C# and playing with the mobile.

Updated on June 24, 2022

Comments

  • joe_coolish
    joe_coolish over 1 year

    I'm working on an async Http crawler that gathers data from various services, and at the moment, I'm working with threadpools that do serial HttpWebRequest calls to post/get data from the services.

    I want to transition over to the async web calls (BeginGetRequestStream and BeginGetResponse), I need some way get the response data and POST stats (% completed with the write, when complete (when complete more important), etc). I currently have an event that is called from the object that spawns/contains the thread, signaling HTTP data has been received. Is there an event in the WebRequests I can attach to to call the already implemented event? That would be the most seamless for the transition.

    Thanks for any help!!

  • joe_coolish
    joe_coolish over 12 years
    Oh, I forgot to mention I might need to support Compact Framework, but if not I'll definitely use WebClient. Is there a CF friendly WebClient?
  • abatishchev
    abatishchev over 12 years
    @Jimmer: For CF HttpWebRequest is only the way