Async Httphandlers in ASP.NET

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();
    }
  }
}

About Mikkel Ovesen

I am a .NET developer, primarily developing apps for the web. I have been working with the web since 1997. I like open-source software and burgers ;)
This entry was posted in Development and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>