Bug in MVC3 - requests never time out. Works fine for aspx pages in same project

前端 未结 3 557
梦如初夏
梦如初夏 2021-01-31 16:33

I\'m seeing this on our production site as well as a small test site I setup just to test this out...

Basically, it appears that requests handled by mvc never time out.

3条回答
  •  有刺的猬
    2021-01-31 17:06

    I found the cause for this, methinks:

    This method is in the WrappedAsyncResult class, which the MvcHandler class uses via BeginProcessRequest:

    public static IAsyncResult BeginSynchronous(AsyncCallback callback, object state, Func func, object tag)
    {
        BeginInvokeDelegate beginDelegate = delegate (AsyncCallback asyncCallback, object asyncState) {
            SimpleAsyncResult result = new SimpleAsyncResult(asyncState);
            result.MarkCompleted(true, asyncCallback);
            return result;
        };
        EndInvokeDelegate endDelegate = _ => func();
        WrappedAsyncResult result = new WrappedAsyncResult(beginDelegate, endDelegate, tag);
        result.Begin(callback, state, -1);
        return result;
    }
    

    where "Begin" is:

    public void Begin(AsyncCallback callback, object state, int timeout)
    {
        bool completedSynchronously;
        this._originalCallback = callback;
        lock (this._beginDelegateLockObj)
        {
            this._innerAsyncResult = this._beginDelegate(new AsyncCallback(this.HandleAsynchronousCompletion), state);
            completedSynchronously = this._innerAsyncResult.CompletedSynchronously;
            if (!completedSynchronously && (timeout > -1))
            {
                this.CreateTimer(timeout);
            }
        }
        if (completedSynchronously && (callback != null))
        {
            callback(this);
        }
    }
    

    EDIT: have come up with a ham-handed way of forcing MVC controller actions to "time out", although the mechanism is a bit brutish:

    public class TimeoutController : Controller
    {
        private bool _isExecuting = false;
        private int _controllerTimeout = 5000;
        private Thread _executingThread;
        private readonly object _syncRoot = new object();
    
        protected override void ExecuteCore()
        {
            _executingThread = Thread.CurrentThread;
            ThreadPool.QueueUserWorkItem(o =>
                {
                    Thread.Sleep(_controllerTimeout);
                    if (_isExecuting)
                    {
                        _executingThread.Abort();
                    }
                });
            base.ExecuteCore();
        }
    
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            _isExecuting = true;
            base.OnActionExecuting(filterContext);
        }
    
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            _isExecuting = false;                
            base.OnActionExecuted(filterContext);
        }
    
        public int ControllerTimeout
        {
            get
            {
                int retVal;
                lock(_syncRoot)
                {
                    retVal = _controllerTimeout;
                }
                return retVal;
            }
            set
            {
                lock(_syncRoot)
                {
                    _controllerTimeout = value;                    
                }
            }
        }
    }
    

提交回复
热议问题