Использование служб с заданной областью в BackgroundService
При регистрации реализаций IHostedService с помощью любого из методов расширения AddHostedService, служба регистрируется как отдельная база данных. Возможны сценарии, в которых потребуется положится на службу с заданной областью. Дополнительные сведения см. в статье Внедрение зависимостей в .NET в разделе "Время существования служб".
В этом руководстве описано следующее:
- Разрешение зависимостей с заданной областью в отдельной базе данных BackgroundService.
- Делегирование работы в службу с заданной областью.
- Реализация
override
BackgroundService.StopAsync(CancellationToken).
Совет
Весь пример исходного кода "Рабочие роли в .NET" доступен для скачивания в Обозревателе примеров. Дополнительные сведения см. в разделе Обзор примеров кода: рабочие роли в .NET.
Необходимые компоненты
- Пакет SDK для .NET 8.0 или более поздней версии
- Интегрированная среда разработки .NET (IDE)
- Можно использовать Visual Studio
Создание нового проекта
Чтобы создать новый проект службы рабочей роли с помощью 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 в окне консоли, чтобы сообщить об отмене.