IHttpAsyncHandler problem

Discussion in 'ASP .Net' started by Alphapage, Feb 18, 2008.

  1. Alphapage

    Alphapage Guest

    Hello,

    You can find my AsyncPage class which inherits from Page and
    IHttpAsyncHandler.
    I inherit my default.aspx page from AsyncPage and put a linkbutton on that
    page and set the PostbackUrl property to
    http://localhost:port/default.aspx?test=1

    I run my app, the page is displayed (no problem), I click the linkbutton
    (the page sleeps during 20000ms, no problem).
    The problem is if I open second tab in Internet Explorer or Firefox and go
    to http://localhost:port/default.aspx when the first is still sleeping, the
    second tab freezes.
    It seems the Asp.Net ThreadPool thread used by the first tab is locked and
    not sent back to the Asp.Net ThreadPool as it should be. So, the second tab
    is pushed in the queue of this strange waiting thread and freezes until the
    first tab finished sleeping.

    How can I bypass this trouble ? (ie: I know all about Asynchrounous pages in
    Asp.Net 2.0, but I want to implement my own threadpool)
    My code seems good and is an example of:
    http://msdn.microsoft.com/msdnmag/issues/03/06/Threading/default.aspx

    Here is my AsyncPage class:
    using System;
    using System.Data;
    using System.Configuration;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Xml.Linq;
    using System.Threading;

    namespace WebApplicationThreadPool
    {
    public class AsyncPage3: Page,IHttpAsyncHandler
    {
    static protected DevelopMentor.ThreadPool _threadPool;

    static AsyncPage3()
    {
    _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; }
    }

    #region IHttpAsyncHandler Members

    public IAsyncResult BeginProcessRequest(HttpContext context,
    AsyncCallback cb, object extraData)
    {

    context.Response.Output.Write("IHttpAsyncHandler.BeginProcessRequest called
    on thread {0}<br/>",
    AppDomain.GetCurrentThreadId());

    AsyncRequestState reqState =
    new AsyncRequestState(context, cb, extraData);


    _threadPool.PostRequest(
    new DevelopMentor.WorkRequestDelegate(ProcessRequest),
    reqState);


    context.Response.Output.Write("IHttpAsyncHandler.BeginProcessRequest called
    on thread {0}<br/>",
    AppDomain.GetCurrentThreadId());

    return reqState;

    }

    public void EndProcessRequest(IAsyncResult result)
    {
    AsyncRequestState reqState = (AsyncRequestState)result;


    reqState.ctx.Response.Output.Write("IHttpAsyncHandler.EndProcessRequest
    called on thread {0}<br/>",

    AppDomain.GetCurrentThreadId());
    }

    #endregion

    void ProcessRequest(object state, DateTime requestTime)
    {
    AsyncRequestState reqState = state as AsyncRequestState;

    if (reqState.ctx.Request.QueryString["test"]=="1")
    Thread.Sleep(20000);
    // Synchronously call base class Page.ProcessRequest
    // as you are now on a thread pool thread.
    base.ProcessRequest(reqState.ctx);


    reqState.ctx.Response.Output.Write("IHttpAsyncHandler.BeginProcessRequest
    called on thread {0}<br/>",
    AppDomain.GetCurrentThreadId());
    //Thread.Sleep(20000);
    // This triggers the asp.net plumbing to call our
    // IHttpAsyncHandler.EndProcessRequest method.
    //
    reqState.CompleteRequest();
    reqState.cb(reqState);
    }

    public class AsyncRequestState : IAsyncResult
    {
    public AsyncRequestState(HttpContext ctx, AsyncCallback cb,
    object extraData)
    {
    this.ctx = ctx;
    this.cb = cb;
    this.extraData = extraData;
    }

    internal HttpContext ctx;
    internal AsyncCallback cb;
    internal object extraData;
    private bool isCompleted = false;
    private ManualResetEvent callCompleteEvent = null;

    internal void CompleteRequest()
    {
    isCompleted = true;

    lock (this)
    {
    if (callCompleteEvent != null)
    {
    callCompleteEvent.Set();
    }
    }
    }

    // IAsyncResult
    //
    public object AsyncState { get { return (extraData); } }
    public bool CompletedSynchronously { get { return (false); } }
    public bool IsCompleted { get { return (isCompleted); } }

    public WaitHandle AsyncWaitHandle
    {
    get
    {
    lock (this)
    {
    if (callCompleteEvent == null)
    {
    callCompleteEvent = new ManualResetEvent(false);
    }

    return (callCompleteEvent);
    }
    }
    }
    }


    }
    }

    Thanks in advance for your help.
     
    Alphapage, Feb 18, 2008
    #1
    1. Advertising

  2. Hello Alphapage,

    My guess is that it's not the page you're waiting for, but the lock on the
    session state. Try disabling the session state for Default.aspx by adding
    the following to the @Page directive like this:

    <%@ Page language="c#" Codebehind="Default.aspx.cs"
    AutoEventWireup="false" Inherits="Default
    EnableSessionState="false" %>

    Every request within the same session needs to wait for the previous page
    to complete redering up to a certain point at which the session is released.

    So if you disable the session, or set it to readonly you shouldn't have this
    problem.

    Jesse


    > Hello,
    >
    > You can find my AsyncPage class which inherits from Page and
    > IHttpAsyncHandler.
    > I inherit my default.aspx page from AsyncPage and put a linkbutton on
    > that
    > page and set the PostbackUrl property to
    > http://localhost:port/default.aspx?test=1
    > I run my app, the page is displayed (no problem), I click the
    > linkbutton
    > (the page sleeps during 20000ms, no problem).
    > The problem is if I open second tab in Internet Explorer or Firefox
    > and go
    > to http://localhost:port/default.aspx when the first is still
    > sleeping, the
    > second tab freezes.
    > It seems the Asp.Net ThreadPool thread used by the first tab is
    > locked and
    > not sent back to the Asp.Net ThreadPool as it should be. So, the
    > second tab
    > is pushed in the queue of this strange waiting thread and freezes
    > until the
    > first tab finished sleeping.
    > How can I bypass this trouble ? (ie: I know all about Asynchrounous
    > pages in
    > Asp.Net 2.0, but I want to implement my own threadpool)
    > My code seems good and is an example of:
    > http://msdn.microsoft.com/msdnmag/issues/03/06/Threading/default.aspx
    > Here is my AsyncPage class:
    > using System;
    > using System.Data;
    > using System.Configuration;
    > using System.Linq;
    > using System.Web;
    > using System.Web.Security;
    > using System.Web.UI;
    > using System.Web.UI.HtmlControls;
    > using System.Web.UI.WebControls;
    > using System.Web.UI.WebControls.WebParts;
    > using System.Xml.Linq;
    > using System.Threading;
    > namespace WebApplicationThreadPool
    > {
    > public class AsyncPage3: Page,IHttpAsyncHandler
    > {
    > static protected DevelopMentor.ThreadPool _threadPool;
    > static AsyncPage3()
    > {
    > _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; }
    > }
    > #region IHttpAsyncHandler Members
    >
    > public IAsyncResult BeginProcessRequest(HttpContext context,
    > AsyncCallback cb, object extraData)
    > {
    > context.Response.Output.Write("IHttpAsyncHandler.BeginProcessRequest
    > called
    > on thread {0}<br/>",
    > AppDomain.GetCurrentThreadId());
    > AsyncRequestState reqState =
    > new AsyncRequestState(context, cb, extraData);
    > _threadPool.PostRequest(
    > new
    > DevelopMentor.WorkRequestDelegate(ProcessRequest),
    > reqState);
    > context.Response.Output.Write("IHttpAsyncHandler.BeginProcessRequest
    > called
    > on thread {0}<br/>",
    > AppDomain.GetCurrentThreadId());
    > return reqState;
    >
    > }
    >
    > public void EndProcessRequest(IAsyncResult result)
    > {
    > AsyncRequestState reqState = (AsyncRequestState)result;
    > reqState.ctx.Response.Output.Write("IHttpAsyncHandler.EndProcessReques
    > t called on thread {0}<br/>",
    >
    > AppDomain.GetCurrentThreadId());
    > }
    > #endregion
    >
    > void ProcessRequest(object state, DateTime requestTime)
    > {
    > AsyncRequestState reqState = state as AsyncRequestState;
    > if (reqState.ctx.Request.QueryString["test"]=="1")
    > Thread.Sleep(20000);
    > // Synchronously call base class Page.ProcessRequest
    > // as you are now on a thread pool thread.
    > base.ProcessRequest(reqState.ctx);
    > reqState.ctx.Response.Output.Write("IHttpAsyncHandler.BeginProcessRequ
    > est
    > called on thread {0}<br/>",
    > AppDomain.GetCurrentThreadId());
    > //Thread.Sleep(20000);
    > // This triggers the asp.net plumbing to call our
    > // IHttpAsyncHandler.EndProcessRequest method.
    > //
    > reqState.CompleteRequest();
    > reqState.cb(reqState);
    > }
    > public class AsyncRequestState : IAsyncResult
    > {
    > public AsyncRequestState(HttpContext ctx, AsyncCallback
    > cb,
    > object extraData)
    > {
    > this.ctx = ctx;
    > this.cb = cb;
    > this.extraData = extraData;
    > }
    > internal HttpContext ctx;
    > internal AsyncCallback cb;
    > internal object extraData;
    > private bool isCompleted = false;
    > private ManualResetEvent callCompleteEvent = null;
    > internal void CompleteRequest()
    > {
    > isCompleted = true;
    > lock (this)
    > {
    > if (callCompleteEvent != null)
    > {
    > callCompleteEvent.Set();
    > }
    > }
    > }
    > // IAsyncResult
    > //
    > public object AsyncState { get { return (extraData); } }
    > public bool CompletedSynchronously { get { return (false);
    > } }
    > public bool IsCompleted { get { return (isCompleted); } }
    > public WaitHandle AsyncWaitHandle
    > {
    > get
    > {
    > lock (this)
    > {
    > if (callCompleteEvent == null)
    > {
    > callCompleteEvent = new
    > ManualResetEvent(false);
    > }
    > return (callCompleteEvent);
    > }
    > }
    > }
    > }
    > }
    > }
    > Thanks in advance for your help.
    >

    --
    Jesse Houwing
    jesse.houwing at sogeti.nl
     
    Jesse Houwing, Feb 18, 2008
    #2
    1. Advertising

  3. Alphapage

    Alphapage Guest

    Perfect. Thank you Jesse.
     
    Alphapage, Feb 19, 2008
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. buzz
    Replies:
    1
    Views:
    776
    Scott Allen
    Nov 23, 2004
  2. buzz
    Replies:
    0
    Views:
    613
  3. =?Utf-8?B?QnJhZCBRdWlubg==?=

    Handling Exceptions in an IHttpAsyncHandler Page

    =?Utf-8?B?QnJhZCBRdWlubg==?=, Apr 11, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    838
    =?Utf-8?B?QnJhZCBRdWlubg==?=
    Apr 11, 2005
  4. Nikos Konstas
    Replies:
    1
    Views:
    412
    John Saunders [MVP]
    Jul 11, 2007
  5. UL-Tomten
    Replies:
    0
    Views:
    559
    UL-Tomten
    Dec 9, 2007
Loading...

Share This Page