FindAsync搭配CancellationToken失效问题排查与解决
问题与解决:CancellationToken在MediatR Handler中不生效的排查
问题现象
测试从Activity表取数的Handler时,发现CancellationToken无效:在Postman中取消请求后,Handler里的for循环仍会完整执行5次,后续的FindAsync也能正常返回Activity对象,日志显示循环执行完成5秒后才触发数据库查询。起初按照相关建议调整了FindAsync的传参方式(将查询参数以数组形式传递,最后跟上CancellationToken),但问题依旧。
根因分析
核心问题在于控制器未将请求的CancellationToken传递给MediatR的Send方法,导致Handler接收的CancellationToken从未被触发取消信号,自然无法中断循环和数据库操作。
代码示例
测试用Handler代码(逻辑正确但因控制器传参问题失效)
public class Handler : IRequestHandler<Query, Result<Activity>> { private readonly ReactivitiesContext _context; private readonly ILogger<Activity> _logger; public Handler(ReactivitiesContext context, ILogger<Activity> logger) { _context = context; _logger = logger; } public async Task<Result<Activity>> Handle(Query request, CancellationToken cancellationToken) { try { for (int i = 1; i <= 5; i++) { cancellationToken.ThrowIfCancellationRequested(); await Task.Delay(1000, cancellationToken); _logger.LogInformation($"{i} second(s) have elapsed"); } } catch (Exception) { _logger.LogInformation("Cancellation was done"); } return Result<Activity>.Success(await _context.Activities.FindAsync( new object[] { request.Id }, cancellationToken)); } }
修正后的控制器代码(传递CancellationToken到MediatR)
[HttpGet("{id}")] public async Task<IActionResult> GetActivity(Guid id, CancellationToken token) { return ResultHandler(await Mediator.Send(new Details.Query { Id = id }, token)); }
内容的提问来源于stack exchange,提问作者James Lee
相关产品推荐
相关产品推荐

