You need to enable JavaScript to run this app. Autofac在MediatR后台通知处理器执行完成前提前释放DbContext如何解决
优惠活动
大模型
产品
解决方案
定价
更多

Autofac在MediatR后台通知处理器执行完成前提前释放DbContext如何解决

解决MediatR后台通知DbContext已释放问题的正确方案

核心问题复盘

问题根源是:默认MediatR解析Handler使用当前Web请求的作用域,你把Handler丢到Task.Run后台执行时,请求结束后作用域被销毁,依赖的DbContext、仓储等服务也会被提前释放。你之前直接修改ServiceFactory从根作用域创建全局作用域的方案会引发资源泄漏、线程安全问题,不可长期使用。


正确实现步骤

1. 重构CustomMediator,为每个后台Handler单独创建独立作用域

不要全局修改ServiceFactory的解析逻辑,仅在发布后台通知时为每个任务单独创建作用域,执行完成后自动销毁:

public class CustomMediator : Mediator
{
    private readonly ILifetimeScope _rootLifetimeScope;

    // 注入根生命周期作用域
    public CustomMediator(ServiceFactory serviceFactory, ILifetimeScope lifetimeScope) : base(serviceFactory)
    {
        _rootLifetimeScope = (lifetimeScope as LifetimeScope).RootLifetimeScope;
    }

    protected override Task PublishCore(IEnumerable<Func<INotification, CancellationToken, Task>> allHandlers, INotification notification, CancellationToken cancellationToken)
    {
        foreach (var handler in allHandlers)
        {
            _ = Task.Run(async () =>
            {
                // 为每个后台任务单独创建作用域,执行完自动释放
                await using var handlerScope = _rootLifetimeScope.BeginLifetimeScope();
                // 从新作用域解析Handler,不使用请求作用域创建的实例
                var notificationType = notification.GetType();
                var handlerType = typeof(INotificationHandler<>).MakeGenericType(notificationType);
                var handlerInstance = handlerScope.Resolve(handlerType) as INotificationHandler<INotification>;
                if (handlerInstance != null)
                {
                    await handlerInstance.Handle(notification, cancellationToken);
                }
            }, cancellationToken);
        }
        return Task.CompletedTask;
    }
}

如果需要区分普通同步通知和后台通知,可以新增空的标记接口IBackgroundNotification继承INotification,仅实现该接口的通知走后台作用域逻辑,不影响原有同步通知的正常逻辑。

2. 保留现有注入配置

你当前的DbContext、仓储、MediatR相关注入配置不需要修改,每个独立作用域会自动创建新的Scoped生命周期实例(包括DbContext),不会和请求作用域冲突,也没有线程安全问题。


可选优化

如果你的后台任务执行时间较长、对可靠性要求高,可以搭配ASP.NET Core自带的IHostedService实现任务队列,先把通知存入队列,由后台常驻服务消费执行,避免应用重启时丢失未完成的任务。

内容的提问来源于stack exchange,提问作者Dvornik Xilosof

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 07:54:03