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

.NET 6中BackgroundService注入Scoped服务报错的解决咨询

解决.NET 6中BackgroundService注入Scoped服务的单例依赖错误

错误原因

  • .NET依赖注入有严格的生命周期规则:Singleton(单例)服务不能依赖Scoped(作用域)或Transient(瞬时)服务。
  • 你注册的MyBackgroundService是Singleton(AddHostedService默认注册为单例),但构造函数直接注入了Scoped的Middleware和imeContext;同时Middleware本身也依赖了Scoped的imeContext,这违反了DI的生命周期约束,导致报错。

解决方案:使用IServiceScopeFactory创建作用域

正确的做法是在BackgroundService中注入IServiceScopeFactory,每次执行任务时动态创建一个作用域,从作用域中获取Scoped服务,执行完任务后自动释放作用域,避免长时间持有Scoped服务引发的线程安全或上下文失效问题。

修改后的MyBackgroundService代码

public class MyBackgroundService : BackgroundService
{
    private readonly ILogger<MyBackgroundService> _logger;
    private readonly IServiceScopeFactory _scopeFactory;

    public MyBackgroundService(ILogger<MyBackgroundService> logger, IServiceScopeFactory scopeFactory)
    {
        _logger = logger;
        _scopeFactory = scopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            if (IsTimeToRunTask())
            {
                // 创建新的作用域,所有从该作用域获取的服务都会在作用域释放时被回收
                using var scope = _scopeFactory.CreateScope();
                var serviceProvider = scope.ServiceProvider;

                // 从作用域中获取需要的Scoped服务
                var middleware = serviceProvider.GetRequiredService<Middleware>();
                var context = serviceProvider.GetRequiredService<IMEAmazon.Models.DBModels.imeContext>();

                // 在这里执行你的业务逻辑
                // 示例:调用Middleware的API方法、操作数据库
                // await middleware.CallExternalApiAsync();
                // context.SomeEntities.Add(new Entity());
                // await context.SaveChangesAsync(stoppingToken);
            }

            await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
        }
    }

    private bool IsTimeToRunTask()
    {
        var now = DateTime.UtcNow.AddHours(-6);
        return (now.Hour == 20 && now.Minute == 25) || (now.Hour == 18 && now.Minute == 0);
    }
}

注意事项

  1. 不要修改DbContext的生命周期为Singleton:DbContext不是线程安全的,单例DbContext会导致并发请求时的数据错乱、上下文状态异常等问题,绝对不推荐。
  2. 保持Middleware的Scoped注册:如果你的Middleware封装了业务逻辑(API调用+数据库操作),Scoped生命周期是合理的,每次任务执行时创建新实例,避免状态污染。
  3. 作用域的自动释放:使用using语句包裹作用域,确保任务执行完成后,作用域内的所有Scoped服务都会被正确释放,包括DbContext。

额外建议

如果你的Middleware只是封装业务逻辑的工具类,而非HTTP请求中间件,建议将其重命名为更贴合功能的名称(比如AmazonApiService),避免与ASP.NET Core的请求中间件概念混淆。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 08:50:57