MVC3中的错误——请求永远不会超时。在相同的项目中,对aspx页面工作良好

时间:2023-01-27 10:25:41

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. I've set an executionTimeout in my web.config and turned off debug mode. I've then added an infinite loop of thread.sleeps to both a regular aspx page and an mvc page (the loop is in the controller of the mvc page). The aspx page reliably times out (HttpException (0x80004005): Request timed out.), but the mvc page just spins forever without timing out.

基本上,mvc处理的请求不会超时。我在我的web上设置了一个执行超时。配置和关闭调试模式。然后我添加了一个无限循环的线程。睡眠到常规的aspx页面和mvc页面(循环在mvc页面的控制器中)。aspx页面可靠地超时(HttpException (0x80004005):请求超时),但是mvc页面只是永远旋转而没有超时。

Are there separate settings for mvc (I've looked but haven't found them)? Do mvc requests not timeout by default?

是否有单独的mvc设置(我已经查找过,但是还没有找到)?默认情况下,mvc请求不会超时吗?

Any help on this would be appreciated. I'll gladly email out my small test site if it would help anyone out.

如有任何帮助,我们将不胜感激。如果我的小测试网站能帮助任何人,我会很高兴地发邮件给他们。

Edit: I'm using MVC3.

编辑:我用MVC3。

Contents of my web.config:

我的web . config内容:

<?xml version="1.0"?>

<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>
  <connectionStrings>
    <add name="ApplicationServices"
         connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
         providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Enabled" value="true" />
  </appSettings>

  <system.web>
      <httpRuntime maxRequestLength="16384" executionTimeout="30" />
      <compilation debug="false" targetFramework="4.0">
          <assemblies>
          <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          </assemblies>
      </compilation>

    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="2880" />
    </authentication>

    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
             enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
             maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
             applicationName="/" />
      </providers>
    </membership>

    <profile>
      <providers>
        <clear/>
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/>
      </providers>
    </profile>

    <roleManager enabled="false">
      <providers>
        <clear/>
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
        <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
      </providers>
    </roleManager>

  </system.web>

  <system.webServer>
     <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

3 个解决方案

#1


9  

I found the cause for this, methinks:

我想我找到了原因:

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

这个方法在WrappedAsyncResult类中,MvcHandler类通过BeginProcessRequest使用:

public static IAsyncResult BeginSynchronous<TResult>(AsyncCallback callback, object state, Func<TResult> func, object tag)
{
    BeginInvokeDelegate beginDelegate = delegate (AsyncCallback asyncCallback, object asyncState) {
        SimpleAsyncResult result = new SimpleAsyncResult(asyncState);
        result.MarkCompleted(true, asyncCallback);
        return result;
    };
    EndInvokeDelegate<TResult> endDelegate = _ => func();
    WrappedAsyncResult<TResult> result = new WrappedAsyncResult<TResult>(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:

编辑:已经想出了一种强制MVC控制器动作“超时”的笨拙方法,尽管这种机制有点粗鲁:

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

#2


2  

It should work when these conditions are met:

当满足这些条件时,它应该能够工作:

1) Domain name is not localhost (to test timeout you should use "YourComputerName" instead of "localhost").

1)域名不是localhost(要测试超时,应该使用“YourComputerName”而不是“localhost”)。

2) Project is compiled in Release mode.

2)项目在发布模式下编译。

3) compilation debug="false"

3)编译调试= " false "

if not look here for an alternative (ScriptTimeOut): ASP.NET MVC and httpRuntime executionTimeout

如果没有,请在这里寻找一个替代方法(ScriptTimeOut): ASP。NET MVC和httpRuntime执行超时

Greetings,
Daddy

你好,爸爸

#3


0  

Still happening for me in MVC 4. I have submitted this to microsoft as a bug:

在MVC 4中仍然存在。我把它作为一个bug提交给微软:

https://connect.microsoft.com/VisualStudio/feedback/details/781171/asp-net-mvc-executiontimeout-does-not-work

https://connect.microsoft.com/VisualStudio/feedback/details/781171/asp-net-mvc-executiontimeout-does-not-work

Update:

更新:

Microsoft commented with the following:

微软评论如下:

The execution timeout feature is not advised to be used in MVC applications. You can instead set HttpContext.Server.ScriptTimeout to the desired timeout value. Despite the name, this is a per-request setting and should apply to any ASP.NET request (the name "script" is misleading)

不建议在MVC应用程序中使用执行超时特性。您可以设置HttpContext.Server。将ScriptTimeout设置为所需的超时值。尽管有名称,这是一个每个请求设置,应该适用于任何ASP。NET请求(“脚本”的名称具有误导性)

.

#1


9  

I found the cause for this, methinks:

我想我找到了原因:

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

这个方法在WrappedAsyncResult类中,MvcHandler类通过BeginProcessRequest使用:

public static IAsyncResult BeginSynchronous<TResult>(AsyncCallback callback, object state, Func<TResult> func, object tag)
{
    BeginInvokeDelegate beginDelegate = delegate (AsyncCallback asyncCallback, object asyncState) {
        SimpleAsyncResult result = new SimpleAsyncResult(asyncState);
        result.MarkCompleted(true, asyncCallback);
        return result;
    };
    EndInvokeDelegate<TResult> endDelegate = _ => func();
    WrappedAsyncResult<TResult> result = new WrappedAsyncResult<TResult>(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:

编辑:已经想出了一种强制MVC控制器动作“超时”的笨拙方法,尽管这种机制有点粗鲁:

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

#2


2  

It should work when these conditions are met:

当满足这些条件时,它应该能够工作:

1) Domain name is not localhost (to test timeout you should use "YourComputerName" instead of "localhost").

1)域名不是localhost(要测试超时,应该使用“YourComputerName”而不是“localhost”)。

2) Project is compiled in Release mode.

2)项目在发布模式下编译。

3) compilation debug="false"

3)编译调试= " false "

if not look here for an alternative (ScriptTimeOut): ASP.NET MVC and httpRuntime executionTimeout

如果没有,请在这里寻找一个替代方法(ScriptTimeOut): ASP。NET MVC和httpRuntime执行超时

Greetings,
Daddy

你好,爸爸

#3


0  

Still happening for me in MVC 4. I have submitted this to microsoft as a bug:

在MVC 4中仍然存在。我把它作为一个bug提交给微软:

https://connect.microsoft.com/VisualStudio/feedback/details/781171/asp-net-mvc-executiontimeout-does-not-work

https://connect.microsoft.com/VisualStudio/feedback/details/781171/asp-net-mvc-executiontimeout-does-not-work

Update:

更新:

Microsoft commented with the following:

微软评论如下:

The execution timeout feature is not advised to be used in MVC applications. You can instead set HttpContext.Server.ScriptTimeout to the desired timeout value. Despite the name, this is a per-request setting and should apply to any ASP.NET request (the name "script" is misleading)

不建议在MVC应用程序中使用执行超时特性。您可以设置HttpContext.Server。将ScriptTimeout设置为所需的超时值。尽管有名称,这是一个每个请求设置,应该适用于任何ASP。NET请求(“脚本”的名称具有误导性)

.