You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core:已取消任务滞留在IIS工作进程致应用无响应

解决IIS工作进程中取消任务堆积的问题

当前你的异常处理中间件无法处理用户刷新页面导致的请求取消场景,根源在于请求取消不会抛出常规Exception,而是通过HttpContext.RequestAborted取消令牌触发,现有try/catch逻辑捕获不到这类场景,导致已取消的任务持续占用进程资源直至堆积溢出。

修改中间件以处理取消请求

调整中间件逻辑,同时监听取消令牌事件和捕获OperationCanceledException,确保所有请求取消场景都能被处理:

public class ErrorHandlerMiddleware : IMiddleware
{
    private readonly IErrorLogger errorLogger;

    public ErrorHandlerMiddleware(IErrorLogger errorLogger) => this.errorLogger = errorLogger;

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        try
        {
            // 注册请求取消回调,覆盖未抛出异常的取消场景
            using var cancellationRegistration = context.RequestAborted.Register(async () =>
            {
                await errorLogger.LogExceptionAsync(
                    new OperationCanceledException("用户刷新页面导致请求取消", context.RequestAborted));
            });

            await next(context);

            // 主动检查请求是否已取消
            if (context.RequestAborted.IsCancellationRequested)
            {
                await errorLogger.LogExceptionAsync(
                    new OperationCanceledException("请求已被用户取消", context.RequestAborted));
            }
        }
        catch (OperationCanceledException ex) when (context.RequestAborted.IsCancellationRequested)
        {
            // 捕获并处理因用户取消抛出的异常
            await errorLogger.LogExceptionAsync(ex);
            await HandleCanceledRequestAsync(context);
        }
        catch (Exception ex)
        {
            await errorLogger.LogExceptionAsync(ex);
            await HandleExceptionAsync(context, ex);
        }
    }

    private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        await context.Response.WriteAsync(JsonConvert.SerializeObject(new { exception.Message, exception.StackTrace }));
    }

    private static async Task HandleCanceledRequestAsync(HttpContext context)
    {
        // 返回499状态码(标识客户端主动关闭连接)
        context.Response.StatusCode = 499;
        await context.Response.WriteAsync(JsonConvert.SerializeObject(new { Message = "请求已被用户取消" }));
    }
}

关键优化点说明

  1. 监听取消令牌:通过context.RequestAborted.Register注册回调,确保即使业务代码未抛出取消异常,也能捕获请求取消事件并记录日志。
  2. 捕获取消异常:单独捕获OperationCanceledException并判断是用户触发的取消,返回专用状态码(499),避免与常规异常混淆。
  3. 主动检查取消状态:在执行完后续中间件后,主动检查请求是否已取消,覆盖所有遗漏场景。

额外建议

  • 业务代码响应取消令牌:在所有异步操作(数据库查询、IO操作等)中传入context.RequestAborted令牌,让业务逻辑能及时终止,快速释放资源。
  • 优化用户体验:对于长耗时请求,前端可添加加载状态提示,避免用户频繁刷新页面从源头减少取消请求。
  • 调整IIS配置:适当调整应用池的队列长度和进程回收规则,但这仅为辅助手段,核心还是要从代码层面处理取消请求。

内容的提问来源于stack exchange,提问作者Muhammad Usama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:22:49