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

Azure Web Job中Hosted Service作用域异常:本地报错云端正常

问题:Azure Web Job中BackgroundService注入Scoped服务本地报错但云端正常?

我正在开发一个发布为Azure Web Job的BackgroundService,发现一处异常:该服务在Azure上运行正常,但本地运行时会抛出错误。

复现场景代码

Program.cs

using TestBackgroundJob;

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddScoped<IDummyService, DummyService>();
        services.AddHostedService<Worker>();
    })
    .Build();

await host.RunAsync();

Worker类

public class Worker : BackgroundService
{
        private readonly ILogger<Worker> _logger;
        private readonly IDummyService _dummyService;

        public Worker(ILogger<Worker> logger, IDummyService dummyService)
        {
            _logger = logger;
            _dummyService = dummyService;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
}

本地运行错误

Cannot consume scoped service 'TestBackgroundJob.IDummyService' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.)'

我怀疑在Azure环境中Worker的作用域从单例变为了Scoped,请问实际情况是否如此?


解答

Worker在Azure Web Job环境中依然是单例服务,并没有被改为Scoped。云端不报错的原因是Azure Web Job的宿主环境在服务注入时,未启用本地Generic Host默认的严格作用域验证逻辑,从而绕过了该错误。

但这种写法不符合依赖注入的作用域规范,会导致Scoped服务的生命周期被强制延长至单例级别,可能引发资源泄漏、状态不一致等潜在问题。正确的做法是通过IServiceScopeFactory在需要时创建作用域来获取Scoped服务,修改后的Worker代码如下:

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

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

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                
                // 创建作用域并获取Scoped服务
                using (var scope = _scopeFactory.CreateScope())
                {
                    var dummyService = scope.ServiceProvider.GetRequiredService<IDummyService>();
                    // 执行dummyService相关操作
                }
                
                await Task.Delay(1000, stoppingToken);
            }
        }
}

该写法能在本地和Azure Web Job环境中均遵循依赖注入的作用域规则,避免潜在风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:05:08