有没有办法在Asp.Net core 3.1中手动启动BackgroundService [英] Is there a way to manually start BackgroundService in Asp.Net core 3.1

查看:47
本文介绍了有没有办法在Asp.Net core 3.1中手动启动BackgroundService的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道在 Asp.Net 3.0(或 3.1)之前,要手动启动 BackgroundService,我们可以从 IHostedService 派生它并将 DI 注册更改为:

I know prior to Asp.Net 3.0 (or 3.1), to manually start a BackgroundService, we could derive it from IHostedService instead and change the DI registration to:

services.AddSingleton<IHostedService, CustomHostedService>();

然后通过在构造函数中注入服务,并调用StartAsync()来手动触发服务启动.

and then manually trigger the service start by injecting the service in the constructor, and calling StartAsync().

但是,我似乎无法在 Asp.Net Core 3.1 中做到这一点.查看 StartAsync() 方法的代码,在应用启动完成之前启动后台服务.

However, I can't seem to do that in Asp.Net Core 3.1. Having a look at the code for the StartAsync() method, background services are started before the app startup is completed.

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();
}

手动触发后台服务启动的最佳方法是什么?

What's the best way to manually trigger a background service to start?

基本上,这是我的设置:

Essentially, this is my setup:

后台服务

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谢谢

Essentially this certService properties are only set when a request comes in and executes a middleware. And since when ExecuteAsync() in the background service tries to get an instance of consumer from the factory, is executed regardless, I dont have the IConsumer properly configured Thanks

推荐答案

注入的托管服务从应用开始,到应用结束.框架不为您提供手动控制.应该有这样的潜在原因.当然,您可以使用线程实现自己的解决方案,但如果您希望继续使用 Microsoft 的内置解决方案,您可以使用 排队后台任务.您将启动一个带有空任务队列的后台服务.服务将侦听您要添加到队列中的第一个任务.您可以随时添加任务,然后它就会在后台运行.

Injected Hosted services start with the app and stops with it. Framework doesn't provide you manual control. There should be underlying reasons for that like. Of course, you can implement your own solutions with threads but if your wish to go on with Microsoft's built-in solutions you can use Queued Background Task. You will start a background service with an empty task queue. Service will be listening to your first task to be added to the queue. You can add a task whenever you wish then it will be running at background.

这篇关于有没有办法在Asp.Net core 3.1中手动启动BackgroundService的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆