What is the correct way to create a httphandler that potentially can take time and resources to complete.
Well this article explains it very well:
http://msdn.microsoft.com/en-us/magazine/cc164128.aspx
If you don’t want to read all, you find the best solution in the bottom of the article.
But you can also find the code here, download this library C# Threadpool.
AsyncRequest
class AsyncRequest
{
private AsyncRequestState _asyncRequestState;
public AsyncRequest(AsyncRequestState ars)
{
_asyncRequestState = ars;
}
public void ProcessRequest()
{
// This is where the non-cpu-bound activity would take place, such as
// accessing a Web Service, polling a slow piece of hardware, or
// performing a lengthy database operation. I put the thread to sleep
// for two seconds to simulate a lengthy operation.
Thread.Sleep(2000);
_asyncRequestState._ctx.Response.Output.Write(
"AsyncThread, {0}",
AppDomain.GetCurrentThreadId());
// tell asp.net I am finished processing this request
_asyncRequestState.CompleteRequest();
}
}
AsyncHandler
namespace EssentialAspDotNet.HttpPipeline
{
// AsyncRequestState and AsyncRequest remain the same
// as in the previous example
public class AsyncHandler : IHttpAsyncHandler
{
static DevelopMentor.ThreadPool _threadPool;
static AsyncHandler()
{
_threadPool =
new DevelopMentor.ThreadPool(2, 25, "AsyncPool");
_threadPool.PropogateCallContext = true;
_threadPool.PropogateThreadPrincipal = true;
_threadPool.PropogateHttpContext = true;
_threadPool.Start();
}
public void ProcessRequest(HttpContext ctx)
{
// not used
}
public bool IsReusable
{
get { return false;}
}
public IAsyncResult BeginProcessRequest(HttpContext ctx,
AsyncCallback cb, object obj)
{
AsyncRequestState reqState =
new AsyncRequestState(ctx, cb, obj);
_threadPool.PostRequest(
new DevelopMentor.WorkRequestDelegate(ProcessRequest),
reqState);
return reqState;
}
public void EndProcessRequest(IAsyncResult ar)
{
}
void ProcessRequest(object state, DateTime requestTime)
{
AsyncRequestState reqState = state as AsyncRequestState;
// Take some time to do it
Thread.Sleep(2000);
reqState._ctx.Response.Output.Write(
"AsyncThreadPool, {0}",
AppDomain.GetCurrentThreadId);
// tell asp.net you are finished processing this request
reqState.CompleteRequest();
}
}
}
AsyncPage
namespace EssentialAspDotNet.HttpPipeline
{
public class AsyncPage : Page, IHttpAsyncHandler
{
static protected DevelopMentor.ThreadPool _threadPool;
static AsyncPage()
{
_threadPool =
new DevelopMentor.ThreadPool(2, 25, "AsyncPool");
_threadPool.PropogateCallContext = true;
_threadPool.PropogateThreadPrincipal = true;
_threadPool.PropogateHttpContext = true;
_threadPool.Start();
}
public new void ProcessRequest(HttpContext ctx)
{
// not used
}
public new bool IsReusable
{
get { return false;}
}
public IAsyncResult BeginProcessRequest(HttpContext ctx,
AsyncCallback cb, object obj)
{
AsyncRequestState reqState =
new AsyncRequestState(ctx, cb, obj);
_threadPool.PostRequest(
new DevelopMentor.WorkRequestDelegate(ProcessRequest),
reqState);
return reqState;
}
public void EndProcessRequest(IAsyncResult ar)
{
}
void ProcessRequest(object state, DateTime requestTime)
{
AsyncRequestState reqState = state as AsyncRequestState;
// Synchronously call base class Page.ProcessRequest
// as you are now on a thread pool thread.
base.ProcessRequest(reqState._ctx);
// Once complete, call CompleteRequest to finish
reqState.CompleteRequest();
}
}
}