Why is this HttpWebRequest class unreliable?

S

sfoxover

Hi,

Could someone please give me some suggestions on how to make this class
robust. I need to be able to handle around 20 similtanious requests to
this class which causes a web browser to display a waiting message
while it requests XML data from a third party server. Some requests can
take around 30 seconds.

Usually the first time I do the request it always works. If I try again
without closing the web browser it will fail sometimes. And if I try
from more than 1 web browser at the same time it will fail a lot.

bool CheckAvailable() is used for the requests.

Thanks


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

namespace TestPost
{
/// <summary>
/// Summary description for SamplePost.
/// </summary>
public class SamplePost
{
public static AutoResetEvent m_allDone = null;

public SamplePost()
{
}

private bool CheckAvailable(string strURL, string strXMLPost,string
strUser, string strPassword)
{
// send POST request
m_strURL = strURL;
m_strXMLPost = strXMLPost;
m_strUser = strUser;
m_strPassword = strPassword;

RequestState myRequestState = null;
// send POST request
try
{
// Create a new 'HttpWebRequest' object to the mentioned URL.
HttpWebRequest myHttpWebRequest1 =
(HttpWebRequest)WebRequest.Create(m_strURL);
myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest1;
myRequestState.m_strPostData = m_strXMLPost;
myHttpWebRequest1.ContentType =
"application/x-www-form-urlencoded";
myHttpWebRequest1.Method = "POST";
myHttpWebRequest1.Headers.Add("Cache-Control","no-cache");
myHttpWebRequest1.ContentLength = m_strXMLPost.Length;
myHttpWebRequest1.KeepAlive = true;
myHttpWebRequest1.Credentials = new
NetworkCredential(m_strUser,m_strPassword);

m_allDone = new AutoResetEvent(false);
IAsyncResult result = (IAsyncResult)
myHttpWebRequest1.BeginGetRequestStream(new
AsyncCallback(PostCallback),myRequestState);
// using result.AsyncWaitHandle slips past WaitOne, so trying
threadpool
// result.AsyncWaitHandle.WaitOne(20000,true);
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle, new
WaitOrTimerCallback(TimeoutSocketCallback), myHttpWebRequest1,
DefaultTimeout, true);
m_allDone.WaitOne();

if(!myRequestState.m_bResultOK)
return false;

// Start the asynchronous BeginGetResponse request.
m_allDone = new AutoResetEvent(false);
IAsyncResult result2 = (IAsyncResult)
myHttpWebRequest1.BeginGetResponse(new
AsyncCallback(RespCallback),myRequestState);
ThreadPool.RegisterWaitForSingleObject (result2.AsyncWaitHandle,
new WaitOrTimerCallback(TimeoutSocketCallback), myHttpWebRequest1,
Defines.N_HTTP_REQUEST_TIMEOUT, true);
m_allDone.WaitOne();
myRequestState.response.Close();
}
catch(WebException)
{
return false;
}
catch(Exception)
{
return false;
}
// check reply OK
bool bOK = false;
if(myRequestState != null)
{
string strReply = myRequestState.m_strReply;
bOK = VerifyXMLReply(strReply);
}
return bOK;
}

// send post data
private void PostCallback(IAsyncResult asynchronousResult)
{
RequestState myRequestState = null;
try
{
// Set the State of request to asynchronous.
myRequestState = (RequestState)asynchronousResult.AsyncState;
HttpWebRequest myHttpWebRequest2 =
(HttpWebRequest)myRequestState.request;
// End of the Asynchronus writing .
Stream postStream =
myHttpWebRequest2.EndGetRequestStream(asynchronousResult);
// send any post data
if(!Helpers.IsEmpty(myRequestState.m_strPostData))
{
ASCIIEncoding encoder = new ASCIIEncoding();
// Convert the string into byte array.
byte[] ByteArray = encoder.GetBytes(myRequestState.m_strPostData);
// Write to the stream.
postStream.Write(ByteArray,0,myRequestState.m_strPostData.Length);
}
postStream.Close();
myRequestState.m_bResultOK = true;
m_allDone.Set();
}
catch(WebException e)
{
if(myRequestState != null)
{
myRequestState.m_strErrorText = e.Message;
myRequestState.m_bResultOK = false;
}
}
catch(Exception e)
{
if(myRequestState != null)
{
myRequestState.m_strErrorText = e.Message;
myRequestState.m_bResultOK = false;
}
}
m_allDone.Set();
}

// read response
private void RespCallback(IAsyncResult asynchronousResult)
{
RequestState myRequestState = null;
try
{
// State of request is asynchronous.
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.BufferRead, 0, BUFFER_SIZE, new
AsyncCallback(ReadCallBack), myRequestState);
return;
}
catch(WebException e)
{
if(myRequestState != null)
{
myRequestState.m_bResultOK = false;
myRequestState.m_strErrorText = e.Message;
}
}
m_allDone.Set();
}

// read callback
private void ReadCallBack(IAsyncResult asyncResult)
{
RequestState myRequestState = null;
try
{
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.m_strReply +=
Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read);
IAsyncResult asynchronousResult = responseStream.BeginRead(
myRequestState.BufferRead, 0, BUFFER_SIZE, new
AsyncCallback(ReadCallBack), myRequestState);
return;
}
else
{
myRequestState.m_bResultOK = true;
responseStream.Close();
}
}
catch(WebException e)
{
if(myRequestState != null)
{
myRequestState.m_bResultOK = false;
myRequestState.m_strErrorText = e.Message;
}
}
m_allDone.Set();
}

// Abort the request if the timer fires.
private void TimeoutSocketCallback(object state, bool timedOut)
{
if(timedOut)
{
HttpWebRequest request = state as HttpWebRequest;
if (request != null)
{
request.Abort();
}
}
}
}

// used for asyncronous requests
public class RequestState
{
// This class stores the State of the request.
const int BUFFER_SIZE = 1024;
public string m_strPostData;
public string m_strReply;
public string m_strErrorText;
public bool m_bResultOK;
public byte[] BufferRead;
public HttpWebRequest request;
public HttpWebResponse response;
public Stream streamResponse;
// constructor
public RequestState()
{
BufferRead = new byte[BUFFER_SIZE];
request = null;
streamResponse = null;
m_bResultOK = false;
m_strPostData = "";
m_strErrorText = "";
m_strReply = "";
}
}
}
 
S

Scott Allen

Hi sfoxover:

You have several threading issues in this code. For example,
declaring AutoResetEvent as a static member is begging for your
threads to miss the signal entirely.

My suggestion would be to get rid of all the asynch activity - it's
not buying you anything in this code. The original thread is doing
nothing but waiting for the second thread to finish - so why not skip
the 2nd thread and do all the work with 1?

Try to get it working first, and then see if you need to make some
optimizations.

You'll also want to bump up the number of HTTP connections you can
make to an external machine:
http://odetocode.com/Blogs/scott/archive/2004/06/08/272.aspx

--
Scott
http://www.OdeToCode.com/blogs/scott/

Hi,

Could someone please give me some suggestions on how to make this class
robust. I need to be able to handle around 20 similtanious requests to
this class which causes a web browser to display a waiting message
while it requests XML data from a third party server. Some requests can
take around 30 seconds.

Usually the first time I do the request it always works. If I try again
without closing the web browser it will fail sometimes. And if I try
from more than 1 web browser at the same time it will fail a lot.

bool CheckAvailable() is used for the requests.

Thanks


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

namespace TestPost
{
/// <summary>
/// Summary description for SamplePost.
/// </summary>
public class SamplePost
{
public static AutoResetEvent m_allDone = null;

public SamplePost()
{
}

private bool CheckAvailable(string strURL, string strXMLPost,string
strUser, string strPassword)
{
// send POST request
m_strURL = strURL;
m_strXMLPost = strXMLPost;
m_strUser = strUser;
m_strPassword = strPassword;

RequestState myRequestState = null;
// send POST request
try
{
// Create a new 'HttpWebRequest' object to the mentioned URL.
HttpWebRequest myHttpWebRequest1 =
(HttpWebRequest)WebRequest.Create(m_strURL);
myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest1;
myRequestState.m_strPostData = m_strXMLPost;
myHttpWebRequest1.ContentType =
"application/x-www-form-urlencoded";
myHttpWebRequest1.Method = "POST";
myHttpWebRequest1.Headers.Add("Cache-Control","no-cache");
myHttpWebRequest1.ContentLength = m_strXMLPost.Length;
myHttpWebRequest1.KeepAlive = true;
myHttpWebRequest1.Credentials = new
NetworkCredential(m_strUser,m_strPassword);

m_allDone = new AutoResetEvent(false);
IAsyncResult result = (IAsyncResult)
myHttpWebRequest1.BeginGetRequestStream(new
AsyncCallback(PostCallback),myRequestState);
// using result.AsyncWaitHandle slips past WaitOne, so trying
threadpool
// result.AsyncWaitHandle.WaitOne(20000,true);
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle, new
WaitOrTimerCallback(TimeoutSocketCallback), myHttpWebRequest1,
DefaultTimeout, true);
m_allDone.WaitOne();

if(!myRequestState.m_bResultOK)
return false;

// Start the asynchronous BeginGetResponse request.
m_allDone = new AutoResetEvent(false);
IAsyncResult result2 = (IAsyncResult)
myHttpWebRequest1.BeginGetResponse(new
AsyncCallback(RespCallback),myRequestState);
ThreadPool.RegisterWaitForSingleObject (result2.AsyncWaitHandle,
new WaitOrTimerCallback(TimeoutSocketCallback), myHttpWebRequest1,
Defines.N_HTTP_REQUEST_TIMEOUT, true);
m_allDone.WaitOne();
myRequestState.response.Close();
}
catch(WebException)
{
return false;
}
catch(Exception)
{
return false;
}
// check reply OK
bool bOK = false;
if(myRequestState != null)
{
string strReply = myRequestState.m_strReply;
bOK = VerifyXMLReply(strReply);
}
return bOK;
}

// send post data
private void PostCallback(IAsyncResult asynchronousResult)
{
RequestState myRequestState = null;
try
{
// Set the State of request to asynchronous.
myRequestState = (RequestState)asynchronousResult.AsyncState;
HttpWebRequest myHttpWebRequest2 =
(HttpWebRequest)myRequestState.request;
// End of the Asynchronus writing .
Stream postStream =
myHttpWebRequest2.EndGetRequestStream(asynchronousResult);
// send any post data
if(!Helpers.IsEmpty(myRequestState.m_strPostData))
{
ASCIIEncoding encoder = new ASCIIEncoding();
// Convert the string into byte array.
byte[] ByteArray = encoder.GetBytes(myRequestState.m_strPostData);
// Write to the stream.
postStream.Write(ByteArray,0,myRequestState.m_strPostData.Length);
}
postStream.Close();
myRequestState.m_bResultOK = true;
m_allDone.Set();
}
catch(WebException e)
{
if(myRequestState != null)
{
myRequestState.m_strErrorText = e.Message;
myRequestState.m_bResultOK = false;
}
}
catch(Exception e)
{
if(myRequestState != null)
{
myRequestState.m_strErrorText = e.Message;
myRequestState.m_bResultOK = false;
}
}
m_allDone.Set();
}

// read response
private void RespCallback(IAsyncResult asynchronousResult)
{
RequestState myRequestState = null;
try
{
// State of request is asynchronous.
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.BufferRead, 0, BUFFER_SIZE, new
AsyncCallback(ReadCallBack), myRequestState);
return;
}
catch(WebException e)
{
if(myRequestState != null)
{
myRequestState.m_bResultOK = false;
myRequestState.m_strErrorText = e.Message;
}
}
m_allDone.Set();
}

// read callback
private void ReadCallBack(IAsyncResult asyncResult)
{
RequestState myRequestState = null;
try
{
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.m_strReply +=
Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read);
IAsyncResult asynchronousResult = responseStream.BeginRead(
myRequestState.BufferRead, 0, BUFFER_SIZE, new
AsyncCallback(ReadCallBack), myRequestState);
return;
}
else
{
myRequestState.m_bResultOK = true;
responseStream.Close();
}
}
catch(WebException e)
{
if(myRequestState != null)
{
myRequestState.m_bResultOK = false;
myRequestState.m_strErrorText = e.Message;
}
}
m_allDone.Set();
}

// Abort the request if the timer fires.
private void TimeoutSocketCallback(object state, bool timedOut)
{
if(timedOut)
{
HttpWebRequest request = state as HttpWebRequest;
if (request != null)
{
request.Abort();
}
}
}
}

// used for asyncronous requests
public class RequestState
{
// This class stores the State of the request.
const int BUFFER_SIZE = 1024;
public string m_strPostData;
public string m_strReply;
public string m_strErrorText;
public bool m_bResultOK;
public byte[] BufferRead;
public HttpWebRequest request;
public HttpWebResponse response;
public Stream streamResponse;
// constructor
public RequestState()
{
BufferRead = new byte[BUFFER_SIZE];
request = null;
streamResponse = null;
m_bResultOK = false;
m_strPostData = "";
m_strErrorText = "";
m_strReply = "";
}
}
}
 

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

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top