簡體   English   中英

.NET Core 中的多個后台服務

[英]Multiple Background Services in .NET Core

在 .NET 6 中創建多個后台任務,這些任務在功能方面相互獨立,並根據計划的時間並行/同時運行。 使用Worker class 模板,我能夠創建多個托管/后台服務,並且它們按預期運行。

但是services.AddHostedService<Worker>(); 將被視為 Singleton class 並且我們需要解決作用域依賴性以使服務成為作用域,與作用域服務文檔中的相同。 根據上面鏈接中的示例,示例代碼如下所示,Scoped 服務的接口

  namespace App.ScopedService;
public interface IScopedProcessingService
{
    Task DoWorkAsync(CancellationToken stoppingToken);
} 

和接口的默認實現

namespace App.ScopedService;

public class DefaultScopedProcessingService : IScopedProcessingService
{
    private int _executionCount;
    private readonly ILogger<DefaultScopedProcessingService> _logger;

    public DefaultScopedProcessingService(
        ILogger<DefaultScopedProcessingService> logger) =>
        _logger = logger;

    public async Task DoWorkAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            ++ _executionCount;

            _logger.LogInformation(
                "{ServiceName} working, execution count: {Count}",
                nameof(DefaultScopedProcessingService),
                _executionCount);

            await Task.Delay(10_000, stoppingToken);
        }
    }
}

這是后台服務實現

namespace App.ScopedService;

public sealed class ScopedBackgroundService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ILogger<ScopedBackgroundService> _logger;

    public ScopedBackgroundService(
        IServiceProvider serviceProvider,
        ILogger<ScopedBackgroundService> logger) =>
        (_serviceProvider, _logger) = (serviceProvider, logger);

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation(
            $"{nameof(ScopedBackgroundService)} is running.");

        await DoWorkAsync(stoppingToken);
    }

    private async Task DoWorkAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation(
            $"{nameof(ScopedBackgroundService)} is working.");

        using (IServiceScope scope = _serviceProvider.CreateScope())
        {
            IScopedProcessingService scopedProcessingService =
                scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();

            await scopedProcessingService.DoWorkAsync(stoppingToken);
        }
    }

    public override async Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation(
            $"{nameof(ScopedBackgroundService)} is stopping.");

        await base.StopAsync(stoppingToken);
    }
}

和 Program.cs 將如下所示

using App.ScopedService;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddHostedService<ScopedBackgroundService>();
        services.AddScoped<IScopedProcessingService, DefaultScopedProcessingService>();
    })
    .Build();

await host.RunAsync();

如果我有另一個后台服務,那么我可以重用哪些代碼以及如何解決范圍服務?

您可以創建多個實現 IHostedService 接口的服務,然后像這樣注冊它們:

builder.Services.AddHostedService<HostedServiceA>();
builder.Services.AddHostedService<HostedServiceB>();
builder.Services.AddHostedService<HostedServiceC>();

如果要訪問 singleton 中的范圍服務,最簡單的方法是在構造函數中注入IServiceScopeFactory

public HostedServiceA(IServiceScopeFactory serviceScopeFactory)
{
    _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
}

然后您可以通過調用以下方法訪問方法內的作用域服務:

using var scope = _serviceScopeFactory.CreateScope();
var someScopedService = scope.ServiceProvider.GetService<ISomeScopedService>();
var someOtherScopedService = scope.ServiceProvider.GetService<ISomeOtherScopedService>();

暫無
暫無

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

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