using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace AsyncHttpTest
{
public class RequestState
{
public byte[] requestData;
public byte[] responseData;
public HttpWebRequest request;
public HttpWebResponse response;
public Stream streamRequest;
public Stream streamResponse;
public ManualResetEvent timeoutEvent;
public bool requestAborted;
/// <summary>
/// Close all resources like streams, events...
/// </summary>
public void Close()
{
try
{
timeoutEvent.Close();
streamRequest.Close();
streamResponse.Close();
response.Close();
//
// Null all fields to simplify debugging.
//
requestData = null;
responseData = null;
request = null;
response = null;
streamRequest = null;
streamResponse = null;
timeoutEvent = null;
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
}
class Program
{
private static int RequestTimeout = 10000;
private static void TimeoutCallback(object state, bool timedOut)
{
Trace.TraceInformation(
"TimeoutCallback, timedOut={0}",
timedOut);
try
{
RequestState requestState = (RequestState)state;
lock (requestState)
{
if (timedOut)
{
requestState.requestAborted = true;
requestState.request.Abort();
}
requestState.Close();
}
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
static void Main()
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://AAA.BBB.CCC");
webRequest.Method = "POST";
webRequest.ContentType = "text/xml";
webRequest.Timeout = RequestTimeout;
RequestState requestState = new RequestState();
requestState.request = webRequest;
requestState.timeoutEvent = new ManualResetEvent(false);
requestState.requestData = Encoding.ASCII.GetBytes("@@@@@@@@@");
requestState.request.ContentLength = requestState.requestData.Length;
ThreadPool.RegisterWaitForSingleObject(
requestState.timeoutEvent,
new WaitOrTimerCallback(TimeoutCallback),
requestState,
RequestTimeout,
true);
webRequest.BeginGetRequestStream(
new AsyncCallback(BeginGetRequestStreamCallback),
requestState);
Console.WriteLine("press any key to exit...");
Console.ReadKey();
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
private static void BeginGetRequestStreamCallback(
IAsyncResult asynchronousResult)
{
Trace.TraceInformation(
"BeginGetRequestStreamCallback, IsCompleted={0}, CompletedSynchronously={1}",
asynchronousResult.IsCompleted,
asynchronousResult.CompletedSynchronously);
try
{
RequestState requestState = (RequestState)asynchronousResult.AsyncState;
lock (requestState)
{
if (requestState.requestAborted == true)
{
Trace.TraceInformation(
"BeginGetRequestStreamCallback, requestAborted=true");
return;
}
requestState.streamRequest = requestState.request.EndGetRequestStream(
asynchronousResult);
requestState.streamRequest.BeginWrite(
requestState.requestData,
0,
requestState.requestData.Length,
new AsyncCallback(RequestWriteCallBack),
requestState);
}
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
private static void RequestWriteCallBack(
IAsyncResult asynchronousResult)
{
Trace.TraceInformation(
"RequestWriteCallBack, IsCompleted={0}, CompletedSynchronously={1}",
asynchronousResult.IsCompleted,
asynchronousResult.CompletedSynchronously);
try
{
RequestState requestState = (RequestState)asynchronousResult.AsyncState;
lock (requestState)
{
if (requestState.requestAborted == true)
{
Trace.TraceInformation(
"RequestWriteCallBack, requestAborted=true");
return;
}
requestState.streamRequest.EndWrite(
asynchronousResult);
requestState.request.BeginGetResponse(
new AsyncCallback(BeginGetResponseCallback),
requestState);
}
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
private static void BeginGetResponseCallback(
IAsyncResult asynchronousResult)
{
Trace.TraceInformation(
"BeginGetResponseCallback, IsCompleted={0}, CompletedSynchronously={1}",
asynchronousResult.IsCompleted,
asynchronousResult.CompletedSynchronously);
try
{
RequestState requestState = (RequestState)asynchronousResult.AsyncState;
lock (requestState)
{
if (requestState.requestAborted == true)
{
Trace.TraceInformation(
"BeginGetResponseCallback, requestAborted=true");
return;
}
requestState.response = (HttpWebResponse)requestState.request.EndGetResponse(
asynchronousResult);
//
// TODO: Check response status and begin asynchronous read only if valid status
//
requestState.streamResponse = requestState.response.GetResponseStream();
requestState.responseData = new byte[requestState.response.ContentLength];
requestState.streamResponse.BeginRead(
requestState.responseData,
0,
requestState.responseData.Length,
new AsyncCallback(ResponseReadCallBack),
requestState);
}
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
private static void ResponseReadCallBack(
IAsyncResult asynchronousResult)
{
Trace.TraceInformation(
"ResponseReadCallBack, IsCompleted={0}, CompletedSynchronously={1}",
asynchronousResult.IsCompleted,
asynchronousResult.CompletedSynchronously);
try
{
RequestState requestState = (RequestState)asynchronousResult.AsyncState;
lock (requestState)
{
if (requestState.requestAborted == true)
{
Trace.TraceInformation(
"ResponseReadCallBack, requestAborted=true");
return;
}
int bytesRead = requestState.streamResponse.EndRead(asynchronousResult);
//
// TODO: Not whole response could be read, we need check amount of data read and
// begin new asynchronous read if needed using corresponding offset in the buffer.
//
Trace.TraceInformation(Encoding.ASCII.GetString(requestState.responseData));
requestState.timeoutEvent.Set();
}
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
}
}