为何ASP.NET异步请求常忽略httpRuntime的executionTimeout配置?
为什么ASP.NET异步请求会忽略
<httpRuntime>里的executionTimeout配置? 这个问题本质是ASP.NET同步与异步请求处理机制的核心差异导致的,我来给你拆解清楚:
核心原因:executionTimeout是为同步请求设计的
<httpRuntime executionTimeout="120" />这个配置专门针对同步请求的超时控制——它监控的是ASP.NET分配给请求的初始线程的执行时长。但在异步请求场景下:
- 当代码执行到
await关键字时,ASP.NET会把当前线程释放回线程池,等待异步操作完成后再重新分配线程继续处理请求。 - 此时
executionTimeout的监控对象(初始线程)已经不再处理请求了,自然不会触发超时判定。
而你配置里的requestValidationMode="2.0"和targetFramework="4.7"是会正常作用于异步请求的,只有executionTimeout对异步场景完全无效。
异步请求该怎么控制超时?
先提一句:你的示例代码里c变量一直没递增,会无限循环跑下去,这在生产环境绝对要避免!针对异步请求的超时,推荐这两种方式:
方式1:用CancellationTokenSource手动设置超时
修改代码加入超时令牌,主动控制请求执行时长:
public async Task<HttpResponseMessage> ImAlive() { // 设置120秒超时,和你原本的executionTimeout配置对应 using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(120)); int c = 0; try { do { // 传入取消令牌,超时后会抛出OperationCanceledException await Task.Delay(1000, cts.Token); ILogger.Log("ImAlive!"); c++; // 必须递增变量,否则会无限循环 } while (c < 10000); return Request.CreateResponse(HttpStatusCode.OK); } catch (OperationCanceledException) { return Request.CreateResponse(HttpStatusCode.RequestTimeout); } }
方式2:利用Web API内置的请求取消令牌
ASP.NET Web API会自动为每个请求生成CancellationToken,客户端断开连接或服务器触发超时(注意这是专门的异步请求超时配置,和executionTimeout无关)时,令牌会被取消:
public async Task<HttpResponseMessage> ImAlive(CancellationToken cancellationToken) { int c = 0; try { do { await Task.Delay(1000, cancellationToken); ILogger.Log("ImAlive!"); c++; } while (c < 10000); return Request.CreateResponse(HttpStatusCode.OK); } catch (OperationCanceledException) { return Request.CreateResponse(HttpStatusCode.RequestTimeout); } }
额外提醒
如果是IIS托管的站点,还可以在IIS层面设置连接超时(站点高级设置里),但这是针对TCP连接的超时,和请求执行超时不是一回事,别搞混了。
内容的提问来源于stack exchange,提问作者Leonardo




