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

.NET 8 Worker Service部分服务无法构造问题求助

问题分析与解决方案

核心问题

  1. 生命周期不匹配:Worker作为托管服务默认是Singleton生命周期,而IUnitOfWork注册为Scoped生命周期。.NET DI禁止将短生命周期的Scoped服务注入到长生命周期的Singleton服务中,这是引发构造异常的主要原因。
  2. 提前构建ServiceProvider:program.cs中提前调用BuildServiceProvider()创建了独立容器,与后续host.Build()生成的容器不一致,破坏了DI的正常注册流程。
  3. Worker构造函数冗余:存在无参构造函数可能导致DI容器优先选择它,使依赖服务无法正确注入;同时手动实例化cMain,没有利用已注册的Singleton实例。

分步解决方案

1. 修复生命周期不匹配(推荐方案)

保留IUnitOfWork的Scoped生命周期,在Worker中通过IServiceScopeFactory动态创建Scoped实例:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly cMain _cmain;

    // 移除无参构造函数,仅保留依赖注入的构造函数
    public Worker(ILogger<Worker> logger, IServiceScopeFactory scopeFactory, cMain cmain)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
        _cmain = cmain ?? throw new ArgumentNullException(nameof(cmain));
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // 每次业务逻辑执行时创建独立Scope
            using (var scope = _scopeFactory.CreateScope())
            {
                var uow = scope.ServiceProvider.GetRequiredService<IUnitOfWork>();
                
                var breadCrumb = new BreadCrumb
                {
                    Application = Assembly.GetExecutingAssembly().GetName().Name,
                    DateTime = DateTime.Now,
                    Description = "Test",
                    EnquiryHeader_ID = 1,
                    EventName = "Test",
                    ReferenceID = 1,
                    Result = "Test"
                };

                await uow.BreadCrumbs.AddAsync(breadCrumb);
                uow.Save();
            }

            if (_logger.IsEnabled(LogLevel.Information))
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            }
            await Task.Delay(1000, stoppingToken);
        }
    }
}

2. 修复program.cs中的ServiceProvider问题

取消提前构建容器,在AddDbContext的配置委托中通过服务提供者获取cMain实例:

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddSingleton<cMain>();

// 直接在DbContext配置中获取cMain,无需提前构建容器
builder.Services.AddDbContext<ApplicationDbContext>((sp, options) => 
{
    var cMainInstance = sp.GetRequiredService<cMain>();
    options.UseSqlServer(cMainInstance.ConnectionString);
});

builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
// 若BreadCrumbRepository需要依赖注入,需添加以下注册
// builder.Services.AddScoped<IBreadCrumbRepository, BreadCrumbRepository>();
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

3. 额外检查

确保IBreadCrumbRepository的实现类已正确处理依赖:如果后续需要给BreadCrumbRepository注入其他服务,需将其注册到DI容器中;当前代码中直接在UnitOfWork里实例化的方式可正常运行,但灵活性较低。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:22:32