Note that there are some explanatory texts on larger screens.

plurals
  1. POProblem with IHttpAsyncHandler and ASP.NET "Requests Executing" counter
    primarykey
    data
    text
    <p><h1>Solved:</h1><b>I found the solution to this. </b><s>Not sure why it happens but</s><b> Switching the application pool type to 'classic' from 'integrated' solves the problem. Now the 'Requests Executing' keeps going up, the actual application pool process thread remains low (~31 threads) and the app is <em>very</em> responsive (as it should be). <br><br><s>I'm using .Net 2.0 so maybe there is an issue there - tried to google it but no luck.</s> </b> <hr> <b>See <a href="https://stackoverflow.com/questions/6123453/problem-with-ihttpasynchandler-and-asp-net-requests-executing-counter/6128861#6128861">Joe Enzminger's reply for an explanation</a> </b> <hr> Thank you all again. <br/><br/><i>ps. the code is used for playing pool (billiards) online - windows (free) version <a href="http://poolrebel.com" rel="nofollow noreferrer">here</a> for anyone curious and brave enough to try :)</i></p> <hr/> <p>Hello,</p> <p>I've implemented an IHttpAsyncHandler that client applications "poll" to wait for server notifications. Notifications are generated by other "activities" on the server and the Async Handler does no work at all.</p> <p>The execution steps are:</p> <pre><code>IHttpAsyncHandler.BeginProcessRequest Create AsyncResult instance and add it to a "registered clients" collection return the AsyncResult </code></pre> <p><i>...other server activity will generate notifications to be sent to registered clients...</i></p> <pre><code>AsyncResult.CompleteCall called as a result of the generated notification(s). IHttpAsyncHandler.EndProcessRequest is called The notification(s) attached to the AsyncResult are written to the response stream. </code></pre> <p><b>The problem:</b></p> <p>I've tested this on IIS7 on a VM with Windows Server 2008 SP2 and 1 cpu core. After 12 clients register for notifications (using an HTTP GET on the Async.ashx) the performance is degraded to the point that subsequent clients cannot connect.</p> <p>When I check the ASP.NET performance counters the "Requests Executing" counter goes up with each client registration and stays at 12 (which appears to be its maximum value - probably a thread pool size per CPU). </p> <p>I find this very confusing. I though the whole point of async handlers is to free up threads for other connections. It appears that this is not the case so I must be doing something wrong!</p> <p>Why is ASP.NET consuming a thread while waiting for my AsyncResult to complete? Is this a config issue? Do I need to do something specific to indicate that this is an Async Handler?</p> <p>Thank you, Nikos.</p> <p><b>Edit: Added code below:</b><br></p> <pre><code>public class AsyncResult : IAsyncResult { private AsyncCallback _cb; private object _state; private ManualResetEvent _event; private bool _completed; private bool _completedsynchronously; private HttpContext _context; private byte[] _data; private int _datalength; private object _lock = new object(); public AsyncWaitResult(AsyncCallback cb, object state, HttpContext context) { _context = context; _cb = cb; _state = state; } public void Close() { if (_event != null) { _event.Close(); _event = null; } } public HttpContext Context { get { return _context; } } public Object AsyncState { get { return _state; } } public bool CompletedSynchronously { get { return _completedsynchronously; } } public bool IsCompleted { get { return _completed; } } public byte[] Data { get { return _data; } } public int DataLength { get { return _datalength; } } public WaitHandle AsyncWaitHandle { get { lock (_lock) { if (_event == null) _event = new ManualResetEvent(_completed); return _event; } } } public void CompleteCall(byte[] data, int length, bool completedsynchronously) { _data = data; _datalength = length; _completedsynchronously = completedsynchronously; lock (_lock) { _completed = true; if (_event != null) _event.Set(); } if (_cb != null) _cb(this); } } public class Outbound : IHttpAsyncHandler { public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object state) { AsyncResult asyncresult = new AsyncResult(cb, state, context); RegisteredClients.Instance.Add(asyncresult); return asyncresult; } public void EndProcessRequest(IAsyncResult ar) { AsyncResult result = (AsyncResult)ar; if (result != null) { result.Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); result.Context.Response.ContentType = "application/octet-stream"; result.Context.Response.AddHeader("Connection", "keep-alive"); if (result.Data != null) result.Context.Response.OutputStream.Write(result.Data, 0, result.DataLength); result.Close(); } } public void ProcessRequest(HttpContext context){} public bool IsReusable { get { return true; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload