Поделиться через


Использование служб с заданной областью в BackgroundService

При регистрации реализаций IHostedService с помощью любого из методов расширения AddHostedService, служба регистрируется как отдельная база данных. Возможны сценарии, в которых потребуется положится на службу с заданной областью. Дополнительные сведения см. в статье Внедрение зависимостей в .NET в разделе "Время существования служб".

В этом руководстве описано следующее:

  • Разрешение зависимостей с заданной областью в отдельной базе данных BackgroundService.
  • Делегирование работы в службу с заданной областью.
  • Реализация overrideBackgroundService.StopAsync(CancellationToken).

Совет

Весь пример исходного кода "Рабочие роли в .NET" доступен для скачивания в Обозревателе примеров. Дополнительные сведения см. в разделе Обзор примеров кода: рабочие роли в .NET.

Необходимые компоненты

Создание нового проекта

Чтобы создать новый проект службы рабочей роли с помощью Visual Studio, выберите Файл>Создать>Проект. В диалоговом окне Создание нового проекта выполните поиск по запросу "служба рабочей роли" и выберите шаблон "Служба рабочей роли". Если вы предпочитаете использовать .NET CLI, откройте используемый терминал в рабочем каталоге. Выполните команду dotnet new и замените <Project.Name> именем проекта.

dotnet new worker --name <Project.Name>

Дополнительные сведения о команде .NET CLI для создания проекта службы рабочей роли см. здесь.

Совет

Если вы используете Visual Studio Code, вы можете выполнять команды .NET CLI из интегрированного терминала. Дополнительные сведения см. в статье Visual Studio Code: интегрированный терминал.

Создание служб с заданной областью

Чтобы использовать службы с заданной областью в BackgroundService, создайте область. Для размещенной службы по умолчанию не создается область. Фоновая служба с заданной областью содержит логику фоновой задачи.

namespace App.ScopedService;

public interface IScopedProcessingService
{
    Task DoWorkAsync(CancellationToken stoppingToken);
}

Предыдущий интерфейс определяет единственный метод DoWorkAsync. Чтобы определить реализацию по умолчанию:

  • Служба является асинхронной. Метод DoWorkAsync возвращает Task. В демонстрационных целях в методе DoWorkAsync ожидается задержка в десять секунд.
  • В службу внедряется ILogger:
namespace App.ScopedService;

public sealed class DefaultScopedProcessingService(
    ILogger<DefaultScopedProcessingService> logger) : IScopedProcessingService
{
    private int _executionCount;

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

Размещенная служба создает область для разрешения фоновой службы с заданной областью, чтобы вызвать ее метод DoWorkAsync. DoWorkAsync возвращает объект Task, ожидаемый в ExecuteAsync:

Повторное создание класса рабочей роли

Замените существующий класс Worker следующим кодом C# и переименуйте файл в ScopedBackgroundService.cs:

namespace App.ScopedService;

public sealed class ScopedBackgroundService(
    IServiceScopeFactory serviceScopeFactory,
    ILogger<ScopedBackgroundService> logger) : BackgroundService
{
    private const string ClassName = nameof(ScopedBackgroundService);

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Name} is running.", ClassName);

        await DoWorkAsync(stoppingToken);
    }

    private async Task DoWorkAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Name} is working.", ClassName);

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

            await scopedProcessingService.DoWorkAsync(stoppingToken);
        }
    }

    public override async Task StopAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Name} is stopping.", ClassName);

        await base.StopAsync(stoppingToken);
    }
}

В предыдущем коде создается явная область, и IScopedProcessingService реализация разрешается из службы внедрения зависимостей область фабрике. Разрешенный экземпляр службы ограничен, и ожидается его метод DoWorkAsync.

Замените содержимое файла шаблона Program.cs следующим кодом C#:

using App.ScopedService;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<ScopedBackgroundService>();
builder.Services.AddScoped<IScopedProcessingService, DefaultScopedProcessingService>();

IHost host = builder.Build();
host.Run();

Службы зарегистрированы в (Program.cs). Размещенная служба регистрируется с использованием метода расширения AddHostedService.

Дополнительные сведения о регистрации служб см. в статье Внедрение зависимостей в .NET.

Проверка функциональности службы

Чтобы запустить приложение из Visual Studio, нажмите клавишу F5 или выберите в меню Отладка>Начать отладку. Если вы используете .NET CLI, выполните команду dotnet run из рабочего каталога:

dotnet run

Дополнительные сведения о выполнении команды .NET CLI см. в статье dotnet run.

Дайте приложению немного поработать, чтобы создать несколько приращений счетчика выполнения. Должен появиться похожий результат:

info: App.ScopedService.ScopedBackgroundService[0]
      ScopedBackgroundService is running.
info: App.ScopedService.ScopedBackgroundService[0]
      ScopedBackgroundService is working.
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService working, execution count: 1
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\scoped-service
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService working, execution count: 2
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService working, execution count: 3
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService working, execution count: 4
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: App.ScopedService.ScopedBackgroundService[0]
      ScopedBackgroundService is stopping.

Если приложение запускается из Visual Studio, выберите Отладка>Остановить отладку. Кроме того, можно нажать клавиши CTRL + C в окне консоли, чтобы сообщить об отмене.

См. также