我有以下控制器:
[TimeoutFilter]
public abstract class BaseController: Controller
{
}
public class IntegrationTestController : BaseController
{
[HttpGet]
public ActionResult TimeoutSeconds()
{
return Content(HttpContext.Server.ScriptTimeout.ToString(CultureInfo.InvariantCulture));
}
[HttpGet]
public ActionResult ForceTimeout()
{
var timeoutWindow = TimeoutFilter.TimeoutSeconds;
Thread.Sleep((timeoutWindow + 5) * 1000);
return Content("This should never get returned, mwahahaaa!");
}
}
对于我的测试场景,我在TimeoutFilter
中使用了5秒的配置设置,我知道这是有效的,因为当我的测试调用TimeoutSeconds
时,我得到正确的值5,但是当测试调用ForceTimeout
,我的HTTP响应为200,而我的回复从未返回过{&1;}。文本。
过滤器:
public class TimeoutFilter : ActionFilterAttribute
{
internal const string TimeoutSecondsSettingsKey = "MvcActionTimeoutSeconds";
internal static int TimeoutSeconds;
public TimeoutFilter()
{
TimeoutSeconds = int.Parse(ConfigurationManager.AppSettings[TimeoutSecondsSettingsKey]);
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Controller.ControllerContext.HttpContext.Server.ScriptTimeout = TimeoutSeconds;
base.OnActionExecuting(filterContext);
}
}
答案 0 :(得分:11)
即使按照用户Erik Funkenbusch建议的ScriptTimeout
设置debug="false"
,我也无法通过设置web.config
属性来实现此功能:
<configuration>
<system.web>
<compilation debug="false" targetFramework="4.5"/>
...
它继续返回“永远不会返回”的文字,而不是在Thread.Sleep
期间超时。
值得注意的是,我还将Thread.Sleep
扩展到超过Server.ScriptTimeout
默认值110秒,但它最终仍返回相同的文本而不是超时。
然后我尝试在executionTimeout
:
web.config
<configuration>
<system.web>
<httpRuntime targetFramework="4.5" executionTimeout="5"/>
...
如果您现在要向TimeoutFilter
添加断点,您会发现ScriptTimeout
值已设置为executionTimeout
的{{1}}值。唉,这对我来说仍然无效(无论是web.config
)。
然后我发现this link关于debug="false"
和ScriptTimeout
没有使用与您描述的类似设置。帖子中的第一个回复描述了使用executionTimeout
,并且还提到超时将延迟5到15秒。即使使用大debug="false"
值,我仍然没有运气。本文中的第二个回复表明Thread.Sleep
配置设置是executionTimeout
属性的替代(显然是经典ASP中使用的COM接口)。此回复表明,如果不使用自己的超时逻辑,则无法设置特定的超时。
此外,我接着遇到了following (more recent) link,其中第一个回复表明在MVC中关闭了超时。进一步的回复表明这是因为MVCHandler
(选择将处理ScriptTimeout
的控制器)是HTTPRequest
因为它可能正在执行另一个请求(这是重点)因此,它在内部切换超时状态(这是我从阅读此链接收集的内容)。它必须与IHttpAsyncHandler
一起使用,但使用asp.net
似乎是this answer中可接受的方式。
该链接表明添加以下行将允许它工作(但不在中型信任应用程序中):
ScriptTimeout
因此,请将System.Web.HttpContext.Current.GetType().GetField("_timeoutState", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(System.Web.HttpContext.Current, 1);
TimeoutFilter
更改为:
OnActionExecuting()
并设置public override void OnActionExecuting(ActionExecutingContext filterContext)
{
System.Web.HttpContext.Current.GetType().GetField("_timeoutState", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(System.Web.HttpContext.Current, 1);
base.OnActionExecuting(filterContext);
}
:
web.config
允许超时工作,但在第一篇文章中提到了轻微的5秒延迟。
注意:使用此方法不允许您在过滤器中设置<configuration>
<system.web>
<compilation debug="false" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5" executionTimeout="5"/>
...
属性。尝试设置ScriptTimeout
并覆盖ScriptTimeout
中设置的值似乎不起作用。
答案 1 :(得分:9)
您使用的是调试版本吗?
从ScriptTimeout文档:
http://msdn.microsoft.com/en-us/library/system.web.httpserverutility.scripttimeout(v=vs.110).aspx
如果在Web.config文件中将编译元素的debug属性设置为true,则将忽略ScriptTimeout的值。
此外,由于此值与httpRuntime元素上设置的值相同,我真的不明白这一点,因为您可以在网络中配置该设置.config而不是。
编辑:
Dangerous在查找详细信息方面做得很好,事实上,ScriptTimeout在异步管道中是不受支持的(我认为MVC至少是MVC4,以及WebApi ......即使不使用异步方法)< / p>
&#34;解决方法&#34;正如此连接报告所建议的那样:
使用[AsyncTimeout]
属性,并将取消令牌作为参数,然后定期调用CanclationToken.ThrowIfCancelationRequested
,或以异步方式使用取消令牌。
以下是一个例子:
[AsyncTimeout(5000)]
public async Task<ContentResult> Index(CancellationToken ct)
{
await Task.Delay(10 * 1000, ct);
return Content("This should never get returned, mwahahaaa!");
}
这会在5秒后抛出一个带有YSOD的OperationCanceled异常。这样做的好处是它甚至可以在调试模式下工作;)