ASP.NET Core 6 如何获取服务实例 解决host.Services未定义问题
问题1:host.Services未定义的解决方法
原因:你调用host.Services.GetRequiredService的时机不对。AddQueueService是IServiceCollection的扩展方法,执行这个方法的阶段仅负责服务注册,服务容器还未构建完成,自然不存在host实例,也没法解析服务。
正确修改步骤:
- 首先删除
QueueServiceExtensions类里报错的两行代码,调整后的扩展方法如下:
public static class QueueServiceExtensions { public static void AddQueueService(this IServiceCollection services, IConfiguration configuration) { services.AddSingleton<MonitorLoop>(); services.AddHostedService<QueuedHostedService>(); services.AddSingleton<IBackgroundTaskQueue>(_ => { if (!int.TryParse(configuration["QueueCapacity"], out var queueCapacity)) { queueCapacity = 100; } return new DefaultBackgroundTaskQueue(queueCapacity); }); } }
- 在
Program.cs中,调用builder.Build()拿到构建完成的应用实例后,再解析MonitorLoop实例并启动:
var app = builder.Build(); // 省略中间的中间件配置代码... // 新增以下代码,放在app.Run()之前 var monitorLoop = app.Services.GetRequiredService<MonitorLoop>(); monitorLoop.StartMonitorLoop(); app.Run();
问题2:用后台作用域服务承载MonitorLoop是否是更优实践
是的,这是更推荐的做法,优势如下:
- 不需要手动管理服务的解析和启动逻辑,框架会自动在应用启动/停止时触发对应生命周期方法,天然支持优雅停机
- 当
MonitorLoop内部需要依赖作用域服务时,只需要注入IServiceScopeFactory手动创建作用域即可,不会出现生命周期不匹配的问题 - 内置异常处理机制,避免手动启动的服务异常导致进程无感知退出
改造方案:
让MonitorLoop继承BackgroundService抽象类,把启动逻辑放到ExecuteAsync方法中:
public class MonitorLoop : BackgroundService { // 原有构造函数和其他逻辑不变 protected override async Task ExecuteAsync(CancellationToken stoppingToken) { // 把原StartMonitorLoop方法的逻辑移到这里,用stoppingToken作为停止信号 // 原有的循环逻辑监听stoppingToken.IsCancellationRequested即可响应应用停止事件 } }
之后把AddQueueService里的services.AddSingleton<MonitorLoop>()改为services.AddHostedService<MonitorLoop>()即可,不需要再手动解析启动,框架会自动处理生命周期。
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

