It was timing out in production, but not under development.
It seems that if you set debug="true" in your web.config it's designed not to time out (you wouldn't want timeouts while you're debugging now would you).
So to test this I turned off debugging and set a short timeout
e.g.
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="false"> <httpRuntime executionTimeout="5"/>
I could then reproduce the exception:
Request timed out.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.Exception Details: System.Web.HttpException: Request timed out.Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
|
Stack Trace:
[HttpException (0x80004005): Request timed out.]
|
My solution was to wrap the synchronous handler inside an asynchronous one.
e.g.
<%@ WebHandler Language="C#" Class="GenericAsyncHandler" %> using System; using System.Web; /// <remarks> /// Borrowed heavily from http://msdn.microsoft.com/en-us/library/ms227433(v=vs.100).aspx /// </remarks> public class GenericAsyncHandler : IHttpAsyncHandler { /// <summary> /// Shouldn't get any 'plain' requests /// </summary> /// <param name="context"></param> public void ProcessRequest(HttpContext context) { throw new NotImplementedException(); } public bool IsReusable { get { return false; } } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { var async = new GenericAsyncHandlerResult(cb, context, extraData); async.StartAsyncWork(); return async; } public void EndProcessRequest(IAsyncResult result) { } } internal class GenericAsyncHandlerResult : IAsyncResult { public AsyncCollectJobDiagnostics(AsyncCallback callback, HttpContext context, Object state) { _callback = callback; _context = context; _state = state; _completed = false; } public void StartAsyncWork() { ThreadPool.QueueUserWorkItem(StartAsyncTask, null); } private void StartAsyncTask(Object workItemState) { // Simply instantiate the current implementation and 'process' the request using it. new GenericHandler().ProcessRequest(_context); // we're done _completed = true; _callback(this); } private bool _completed; private readonly Object _state; private readonly AsyncCallback _callback; private readonly HttpContext _context; bool IAsyncResult.IsCompleted { get { return _completed; } } WaitHandle IAsyncResult.AsyncWaitHandle { get { return null; } } Object IAsyncResult.AsyncState { get { return _state; } } bool IAsyncResult.CompletedSynchronously { get { return false; } } } }
No comments:
Post a Comment