Jin*_*ish 6 c# asp.net-core asp.net-core-3.1 ihostedservice
我知道在Asp.Net 3.0(或3.1)之前,要手动启动BackgroundService,我们可以从中派生它IHostedService并将DI注册更改为:
services.AddSingleton<IHostedService, CustomHostedService>();
Run Code Online (Sandbox Code Playgroud)
然后通过在构造函数中注入服务并调用 来手动触发服务启动StartAsync()。
但是,我似乎无法在 Asp.Net Core 3.1 中做到这一点。看一下该StartAsync()方法的代码,后台服务是在应用程序启动完成之前启动的。
public async Task StartAsync(CancellationToken cancellationToken = default)
{
_logger.Starting();
await _hostLifetime.WaitForStartAsync(cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
_hostedServices = Services.GetService<IEnumerable<IHostedService>>();
foreach (var hostedService in _hostedServices)
{
// Fire IHostedService.Start
await hostedService.StartAsync(cancellationToken).ConfigureAwait(false);
}
// Fire IApplicationLifetime.Started
_applicationLifetime?.NotifyStarted();
_logger.Started();
}
Run Code Online (Sandbox Code Playgroud)
手动触发后台服务启动的最佳方法是什么?
本质上,这是我的设置:
后台服务
public MyBackgroundService(Func<string, IConsumer> consumerFactory)
{
_consumerFactory = consumerFactory ?? throw new ArgumentNullException(nameof(consumerFactory));
}
Run Code Online (Sandbox Code Playgroud)
消费者工厂注册
services.AddSingleton<Func<string, IConsumer>>(provider => providerName => provider.ConfigureConsumer(environment, providerName));
private static IConsumer ConfigureConsumer(this IServiceProvider provider, IHostEnvironment environment, string provideName)
{
if (string.IsNullOrEmpty(provideName))
throw new ArgumentNullException(nameof(provideName));
var options = provider.GetRequiredService<IOptions<ConsumerConfig>>();
if (options?.Value == null)
throw new ArgumentNullException(nameof(options));
return environment.IsDevelopment()
? new Consumer(options, provider.GetTopics())
: new Consumer((IOptions<ConsumerConfig>)options.SetSecurityOptions(provider), provider.GetTopics());
}
private static IOptions<Config> SetSecurityOptions(this IOptions<Config> config, IServiceProvider provider)
{
var certService = provider.GetRequiredService<IVaultCertificateService>();
...
return config;
}
Run Code Online (Sandbox Code Playgroud)
本质上,这个certService属性仅在请求传入并执行中间件时设置。由于ExecuteAsync()在后台服务尝试从工厂获取消费者实例时,无论如何都会执行,我没有正确配置 IConsumer 谢谢