Usar serviços com escopo em um BackgroundService
Quando você registra implementações de usar qualquer um dos métodos de IHostedServiceAddHostedService extensão - o serviço é registrado como um singleton. Pode haver cenários em que você gostaria de confiar em um serviço com escopo. Para obter mais informações, consulte Injeção de dependência no .NET: Tempos de vida do serviço.
Neste tutorial, irá aprender a:
- Resolva dependências com escopo em um único tonelada BackgroundService.
- Delegue o trabalho a um serviço com escopo.
- Implementar um
override
de BackgroundService.StopAsync(CancellationToken).
Gorjeta
Todo o código-fonte de exemplo "Workers in .NET" está disponível no Navegador de Amostras para download. Para obter mais informações, consulte Procurar exemplos de código: Trabalhadores no .NET.
Pré-requisitos
- O SDK do .NET 8.0 ou posterior
- Um ambiente de desenvolvimento integrado (IDE) .NET
- Sinta-se à vontade para usar o Visual Studio
Criar um novo projeto
Para criar um novo projeto do Serviço de Trabalho com o Visual Studio, selecione Arquivo>Novo>Projeto....Na caixa de diálogo Criar um novo projeto, procure por "Serviço de Trabalho" e selecione Modelo de Serviço de Trabalhador. Se você preferir usar a CLI do .NET, abra seu terminal favorito em um diretório de trabalho. Execute o comando e substitua o dotnet new
pelo nome do <Project.Name>
projeto desejado.
dotnet new worker --name <Project.Name>
Para obter mais informações sobre o comando .NET CLI new worker service project, consulte dotnet new worker.
Gorjeta
Se você estiver usando o Visual Studio Code, poderá executar comandos da CLI do .NET a partir do terminal integrado. Para obter mais informações, consulte Visual Studio Code: Integrated Terminal.
Criar serviços com escopo
Para usar serviços com escopo em um , crie um BackgroundService
escopo. Nenhum escopo é criado para um serviço hospedado por padrão. O serviço em segundo plano com escopo contém a lógica da tarefa em segundo plano.
namespace App.ScopedService;
public interface IScopedProcessingService
{
Task DoWorkAsync(CancellationToken stoppingToken);
}
A interface anterior define um único DoWorkAsync
método. Para definir a implementação padrão:
- O serviço é assíncrono. O
DoWorkAsync
método retorna umTask
arquivo . Para fins de demonstração, espera-se um atraso de dez segundos noDoWorkAsync
método. - Um ILogger é injetado no serviço.:
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);
}
}
}
O serviço hospedado cria um escopo para resolver o serviço em segundo plano com escopo para chamar seu DoWorkAsync
método. DoWorkAsync
Devolve um Task
, que é aguardado em ExecuteAsync
:
Reescrever a classe Worker
Substitua a classe existente Worker
pelo seguinte código C# e renomeie o arquivo para 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);
}
}
No código anterior, um escopo explícito é criado e a implementação é resolvida a IScopedProcessingService
partir da fábrica de escopo do serviço de injeção de dependência. A instância de serviço resolvida tem escopo e seu DoWorkAsync
método é aguardado.
Substitua o conteúdo do arquivo .cs programa modelo com o seguinte código C#:
using App.ScopedService;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<ScopedBackgroundService>();
builder.Services.AddScoped<IScopedProcessingService, DefaultScopedProcessingService>();
IHost host = builder.Build();
host.Run();
Os serviços estão registados no (Programa.cs). O serviço hospedado é registrado com o AddHostedService
método de extensão.
Para obter mais informações sobre como registrar serviços, consulte Injeção de dependência no .NET.
Verificar a funcionalidade do serviço
Para executar o aplicativo do Visual Studio, selecione F5 ou selecione a opção de menu Depurar Iniciar Depuração>. Se você estiver usando a CLI do .NET, execute o dotnet run
comando no diretório de trabalho:
dotnet run
Para obter mais informações sobre o comando .NET CLI run, consulte dotnet run.
Deixe o aplicativo ser executado por um pouco para gerar vários incrementos de contagem de execução. Você verá uma saída semelhante à seguinte:
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.
Se estiver executando o aplicativo de dentro do Visual Studio, selecione Depurar Parar Depuração>.... Como alternativa, selecione Ctrl + C na janela do console para sinalizar o cancelamento.