True asynchronous HttpWebRequest implementation with abort and timeout

A

Alexander

Hi,

I'm tired of seeing all these asynchronous HttpWebRequest
implementations that still tend to use a seperate thread or they just
block.

A Question:

1) How do I implement a cancel method that aborts the request?
HttpWebRequest.Abort() method does just that, but I don't see how the
Cancel() method can get access to the RequestState, as request states
are passed
around in asynchronous object manner?

Found at MSDN under the HttpWebRequest.BeginGetResponse() and modified
it into a class:

using System;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using System.Threading;

namespace Http
{
class RequestState
{
const int BUFFER_SIZE = 1024;
public StringBuilder requestData;
public byte[] _readbuf;
public HttpWebRequest request;
public HttpWebResponse response;
public Stream streamResponse;

public RequestState()
{
_readbuf = new byte[BUFFER_SIZE];
requestData = new StringBuilder("");
request = null;
streamResponse = null;
}
}

class HttpGet
{
public static ManualResetEvent allDone= new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;
const int DefaultTimeout = 2 * 60 * 1000; // 2 minutes timeout

private void TimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
HttpWebRequest request = state as HttpWebRequest;
if (request != null)
{
request.Abort();
Console.WriteLine("Timeout!");
}
}
}

private void RespCallback(IAsyncResult asynchronousResult)
{
try
{
// State of request is asynchronous.
RequestState myRequestState=(RequestState)
asynchronousResult.AsyncState;
HttpWebRequest myHttpWebRequest=myRequestState.request;
myRequestState.response = (HttpWebResponse)
myHttpWebRequest.EndGetResponse(asynchronousResult);

// Read the response into a Stream object.
Stream responseStream =
myRequestState.response.GetResponseStream();
myRequestState.streamResponse=responseStream;

// Begin the Reading of the contents of the HTML page and print it
to the console.
IAsyncResult asynchronousInputRead =
responseStream.BeginRead(myRequestState._readbuf, 0, BUFFER_SIZE, new
AsyncCallback(ReadCallBack), myRequestState);
return;
}
catch(WebException e)
{
Console.WriteLine("\nRespCallback Exception raised!");
Console.WriteLine("\nMessage:{0}",e.Message);
Console.WriteLine("\nStatus:{0}",e.Status);
}
allDone.Set();
}

private void ReadCallBack(IAsyncResult asyncResult)
{
try
{
RequestState myRequestState =
(RequestState)asyncResult.AsyncState;
Stream responseStream = myRequestState.streamResponse;
int read = responseStream.EndRead( asyncResult );
// Read the HTML page and then print it to the console.
if (read > 0)
{
myRequestState.requestData.Append(Encoding.GetEncoding(1252).GetString(myRequestState._readbuf,
0, read));
IAsyncResult asynchronousResult = responseStream.BeginRead(
myRequestState._readbuf, 0, BUFFER_SIZE, new
AsyncCallback(ReadCallBack), myRequestState);
return;
}
else
{
Console.WriteLine("\nThe contents of the Html page are : ");
if(myRequestState.requestData.Length>1)
{
string stringContent;
stringContent = myRequestState.requestData.ToString();
Console.WriteLine(stringContent);
}
Console.WriteLine("Press any key to continue..........");
//Console.ReadLine();

responseStream.Close();
}

}
catch(WebException e)
{
Console.WriteLine("\nReadCallBack Exception raised!");
Console.WriteLine("\nMessage:{0}",e.Message);
Console.WriteLine("\nStatus:{0}",e.Status);
}
allDone.Set();
}

/* Needs to be implemented! Problem: how to access the
httpwebrequest to call Abort()*/
public void Cancel()
{

}

public void Get(string url)
{
try
{
// Create a HttpWebrequest object to the desired URL.
HttpWebRequest myHttpWebRequest=
(HttpWebRequest)WebRequest.Create(url);


/**
* If you are behind a firewall and you do not have your browser
proxy setup
* you need to use the following proxy creation code.

// Create a proxy object.
WebProxy myProxy = new WebProxy();

// Associate a new Uri object to the _wProxy object, using the
proxy address
// selected by the user.
myProxy.Address = new Uri("http://myproxy");


// Finally, initialize the Web request object proxy property with
the _wProxy
// object.
myHttpWebRequest.Proxy=myProxy;
***/

// Create an instance of the RequestState and assign the previous
myHttpWebRequest
// object to it's request field.
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;


// Start the asynchronous request.
IAsyncResult result=
(IAsyncResult) myHttpWebRequest.BeginGetResponse(new
AsyncCallback(RespCallback),myRequestState);

// this line impliments the timeout, if there is a timeout, the
callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle,
new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest,
DefaultTimeout, true);
}
catch(WebException e)
{
Console.WriteLine("\nMain Exception raised!");
Console.WriteLine("\nMessage:{0}",e.Message);
Console.WriteLine("\nStatus:{0}",e.Status);
Console.WriteLine("Press any key to continue..........");
}
catch(Exception e)
{
Console.WriteLine("\nMain Exception raised!");
Console.WriteLine("Source :{0} " , e.Source);
Console.WriteLine("Message :{0} " , e.Message);
Console.WriteLine("Press any key to continue..........");
Console.Read();
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top