MediatR全局异常处理器重复执行问题排查求助
问题根源
你的全局异常处理器重复执行的核心原因是未标记异常已处理:MediatR的异常处理管道会遍历所有匹配的IRequestExceptionHandler实现,若当前处理器未通过RequestExceptionHandlerState标记异常已处理,管道会继续传播异常,导致该全局处理器(因泛型约束匹配所有异常)被重复触发。
解决方案
1. 标记异常已处理
在日志记录完成后,调用state.SetHandled或state.SetException终止异常传播,避免后续重复触发处理器:
修改后的GlobalRequestExceptionHandler代码:
public class GlobalRequestExceptionHandler<TRequest, TResponse, TException>(IMediator mediator, ILoggerService loggerService) : IRequestExceptionHandler<TRequest, TResponse, TException> where TRequest : notnull where TException : Exception { private readonly IMediator _mediator = mediator; private readonly ILoggerService _loggerService = loggerService; public async Task Handle(TRequest request, TException exception, RequestExceptionHandlerState<TResponse> state, CancellationToken cancellationToken) { try { if (IsLogSystemErrorCommandException(request)) return; var systemError = SystemError.Create(request.GetType().Name, exception.GetType().Name, exception.Message, exception.StackTrace, VentureDomain.Common, VentureModule.Common); var command = new LogSystemErrorCommand(systemError); await _mediator.Send(command, cancellationToken); // 标记异常已处理,终止管道传播 // 若TResponse为值类型或需要特定失败响应,替换为对应实例 state.SetHandled(default); } catch (Exception ex) { _loggerService.Log(ex.Message, LogLevel.Error); // 即使日志记录失败,也要标记异常已处理,防止无限循环 state.SetHandled(default); } } private bool IsLogSystemErrorCommandException(object? errorObject) { return errorObject?.GetType() == typeof(LogSystemErrorCommand); } }
如果你的TResponse类型不允许default值(比如自定义的Result类型),可以构造合法的失败响应传入:
// 假设Result是你的响应类型,提供失败构造方法 state.SetHandled((TResponse)(object)_resultService.CreateFailure("系统异常已记录"));
2. 检查是否重复注册处理器
确认AddSystemSurveillanceRequestHandlers扩展方法仅被调用一次,避免处理器被多次注册:
// Program.cs/Startup.cs中确保只调用一次 builder.Services.AddMediatR(cfg => { cfg.AddSystemSurveillanceRequestHandlers(); // 其他MediatR配置逻辑 });
额外提醒
- 避免在异常处理器中抛出未处理的异常,否则会导致异常传播到上层(如ASP.NET全局异常中间件),可能再次触发MediatR的异常处理流程。
- 若需保留原始异常的传播(比如让上层处理HTTP响应状态码),可调用
state.SetException(exception),但需确保不会导致重复触发处理器。
内容的提问来源于stack exchange,提问作者Nico1395
相关产品推荐
相关产品推荐

