.NET 7/8中API请求的CancellationToken失效问题排查求助
问题分析与解决方案
你的代码存在两个核心问题,导致无法正确检测并响应请求取消:
异步操作未绑定取消令牌
你调用await Task.Delay(1000)时没有传入cancellationToken,这意味着即便请求被取消,延迟操作仍会执行完1秒才进入下一次循环检查,无法及时响应取消信号。未处理框架自动抛出的取消异常
当客户端主动中断请求(比如Postman点击取消),ASP.NET Core会触发cancellationToken取消,并在后续代码使用已取消令牌时抛出OperationCanceledException。这个异常默认会被框架捕获并返回500状态码,而非你期望的499。
修改后的代码
using Microsoft.AspNetCore.Mvc; var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.MapGet("/long-running-request", async (CancellationToken cancellationToken) => { var randomId = Guid.NewGuid(); var results = new List<string>(); try { for (int i = 0; i < 100; i++) { // 提前检查取消状态 if (cancellationToken.IsCancellationRequested) return Results.StatusCode(499); // 将取消令牌传入异步操作,确保取消时立即终止延迟 await Task.Delay(1000, cancellationToken); var result = $"{randomId} - Result {i}"; Console.WriteLine(result); results.Add(result); } return Results.Ok(results); } catch (OperationCanceledException) { // 捕获框架抛出的取消异常,返回499状态码 return Results.StatusCode(499); } }) .WithName("GetAllData") .WithOpenApi(); app.Run();
补充说明
- 所有异步I/O操作(数据库查询、HTTP请求、延迟等)都必须传入
CancellationToken,才能在请求取消时立即终止操作,避免资源浪费。 - 499是Nginx定义的「客户端主动关闭连接」状态码,ASP.NET Core无内置该状态码,需手动通过
Results.StatusCode(499)返回。 - 测试时,在Postman发送请求后点击「Cancel」按钮,即可立即触发取消逻辑并返回499。
内容的提问来源于stack exchange,提问作者Łukasz Zapała
相关产品推荐
相关产品推荐

