簡體   English   中英

有沒有辦法在 Asp.Net core 3.1 中手動啟動 BackgroundService

[英]Is there a way to manually start BackgroundService in Asp.Net core 3.1

我知道在 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 謝謝

注入的托管服務從應用程序開始,然后停止。 框架不為您提供手動控制。 應該有這樣的根本原因。 當然,您可以使用線程實現自己的解決方案,但如果您希望 go 使用 Microsoft 的內置解決方案,您可以使用Queued Background Task 您將使用空任務隊列啟動后台服務。 服務將監聽您要添加到隊列中的第一個任務。 您可以隨時添加任務,然后它將在后台運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM