Hangfire+Autofac报错ComponentNotRegisteredException:服务未注册
问题分析与解决
问题根源
你在ServiceCollection中完成了所有服务注册,直接通过serviceCollection.BuildServiceProvider()能正常获取DriverFileService并调用方法,但Hangfire执行任务时触发ComponentNotRegisteredException,核心原因是:
- Hangfire配置了
UseAutofacActivator(builder.Build()),但此处的Autofac容器未包含ServiceCollection中注册的任何服务(你没有将ServiceCollection的注册项导入到Autofac容器构建器中)。 - Hangfire执行后台任务时,会使用配置的Autofac激活器来解析服务,而非你手动创建的
serviceProvider,因此找不到已在ServiceCollection中注册的DriverFileService。
解决方案
1. 整合ServiceCollection与Autofac容器
将ServiceCollection中的所有服务注册导入到Autofac容器构建器中,确保Autofac容器包含完整的服务注册:
// 1. 保留你原有的ServiceCollection服务注册代码 var serviceCollection = new ServiceCollection() .AddScoped<BlobService>() .AddSingleton<IConfiguration>(configuration) .AddDbContext<RedactedDbContext>(opt => opt.UseNpgsql(connectionString)) .AddScoped<ActivityChangeInfoCh>() .AddScoped<SpecificConditionsCh>() .AddScoped<CardIdentificationCh>() .AddScoped<UploadInfoCh>() .AddScoped<CardEventDataCh>() .AddScoped<CardFaultDataCh>() .AddScoped<CardVehiclesUsedCh>() .AddScoped<GNSSPlacesCh>() .AddScoped<HangfireService>() .AddTransient<FileReader>() .AddScoped<ExplorerService>() .AddScoped<DriverFileService>(); // 2. 创建Autofac容器构建器,导入ServiceCollection的注册 var builder = new ContainerBuilder(); builder.Populate(serviceCollection); // 关键步骤:将ServiceCollection服务导入Autofac // 3. 构建完整的Autofac容器 var autofacContainer = builder.Build(); // 4. 配置Hangfire使用该Autofac容器作为激活器 GlobalConfiguration.Configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_180) .UseSimpleAssemblyNameTypeSerializer() .UseColouredConsoleLogProvider() .UseRecommendedSerializerSettings() .UsePostgreSqlStorage(config.GetConnectionString("Hangfire")) .UseAutofacActivator(autofacContainer);
2. 修正RecurringJob的定义
避免直接捕获外部的serviceProvider(Hangfire会序列化委托,ServiceProvider无法被正确序列化且执行时不会使用它),改用Hangfire支持的强类型解析方式:
using (var server = new BackgroundJobServer(options)) { Console.WriteLine("Hangfire Server started. Press any key to exit..."); var manager = new RecurringJobManager(); // 让Hangfire通过Autofac激活器自动解析DriverFileService manager.AddOrUpdate<DriverFileService>( "process2", service => service.Test(), "*/50 * * * * *" ); Console.ReadKey(); }
3. 调整手动调用逻辑(可选)
如果需要保留手动调用TestAvailability()的逻辑,建议改用Autofac容器获取服务,保持容器一致性:
var driverFileService = autofacContainer.Resolve<DriverFileService>(); driverFileService.TestAvailability();
关键注意点
builder.Populate(serviceCollection)是核心,它会将ServiceCollection中所有AddScoped/AddSingleton/AddTransient的注册转换为Autofac对应的生命周期注册。- 不要在Hangfire任务委托中直接引用外部的ServiceProvider或容器实例,Hangfire的任务执行环境与主线程分离,必须依赖配置的激活器解析服务。
内容的提问来源于stack exchange,提问作者Stanley
相关产品推荐
相关产品推荐

