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

C# Worker进程中如何通过依赖注入正确使用Scoped服务

问题原因

错误本质是.NET依赖注入的生命周期限制:AddHostedService 注册的 BackgroundService 派生类默认是单例生命周期,而你将 IVMValidationManager 注册为了范围(Scoped)生命周期。DI容器不允许单例服务直接注入范围服务,避免范围服务被意外提升为单例、造成生命周期混乱,所以直接抛出了这个校验错误。

解决方案

方案1:调整服务生命周期(最简单,适用于无状态/不需要范围隔离的场景)

如果你的 VMValidationManager 不需要每次调用都创建新实例、也没有依赖其他范围服务,直接修改Program.cs中的服务注册代码,把AddScoped改成AddSingleton即可:

.ConfigureServices((hostContext, services) =>
{
    // 将Scoped生命周期调整为Singleton
    services.AddSingleton<IVMValidationManager, VMValidationManager>();
    services.AddHostedService<Worker>();
});

方案2:手动创建范围获取服务(适用于确实需要Scoped生命周期的场景)

如果你的 IVMValidationManager 本身依赖其他Scoped服务、或者确实需要每次调用时使用新的实例,就不要直接在构造函数注入IVMValidationManager,改为注入IServiceProvider,每次使用前手动创建服务范围,从范围内解析服务:
修改Worker类代码如下:

public class Worker : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public Worker(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // 手动创建服务范围
        using var scope = _serviceProvider.CreateScope();
        // 从当前范围解析IVMValidationManager
        var vmValidationManager = scope.ServiceProvider.GetRequiredService<IVMValidationManager>();
        vmValidationManager.RunVMValidationScripts();
    }
}

注意:如果你的Worker是循环执行定时任务的场景,建议把创建范围的逻辑放到每次任务执行的代码块内,保证每次执行都使用新的Scoped服务实例。范围会在using代码块结束后自动释放,范围内解析的所有Scoped服务也会跟着被回收,符合生命周期规范。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:15:05