Я знаю до Asp. Net 3.0 (или 3.1), чтобы вручную запустить BackgroundService, мы могли бы извлечь его из IHostedService
и изменить регистрацию DI на:
services.AddSingleton<IHostedService, CustomHostedService>();
, а затем вручную запустить запуск службы, введя службу в конструктор и вызвав 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();
}
Какой лучший способ вручную запустить фоновую службу для запуска?
По сути, это мои настройки:
Фоновая служба
public MyBackgroundService(Func<string, IConsumer> consumerFactory)
{
_consumerFactory = consumerFactory ?? throw new ArgumentNullException(nameof(consumerFactory));
}
Регистрация фабрики потребителей
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;
}
По сути, свойства certService устанавливаются только при поступлении запроса и выполнении промежуточного программного обеспечения. И поскольку, когда ExecuteAsync()
в фоновом режиме пытается получить экземпляр потребителя с фабрики, выполняется независимо, у меня не правильно настроен IConsumer. Спасибо