Há inúmeros motivos para criar serviços de execução longa, como:
Processamento de dados com uso intensivo de CPU.
Enfileiramento de itens de trabalho em segundo plano.
Execução de operação cronometrada segundo agendamento.
O processamento de serviço em segundo plano geralmente não envolve uma interface do usuário, mas ela pode ser criada em torno deles. Nos primórdios do .NET Framework, os desenvolvedores do Windows podiam criar serviços Windows por esses motivos. Agora, com o .NET, você pode usar o BackgroundService, que é uma implementação de IHostedService, ou implementar o seu.
Com o .NET, você não está mais restrito ao Windows. Você pode desenvolver serviços multiplataforma em segundo plano. Os serviços hospedados estão prontos para registro em log, configuração e DI (injeção de dependência). Eles fazem parte do conjunto de extensões de bibliotecas, o que significa que são fundamentais para todas as cargas de trabalho do .NET que funcionam com o host genérico.
Importante
Instalar o SDK do .NET também instala o Microsoft.NET.Sdk.Worker e o modelo de trabalho. Em outras palavras, depois de instalar o SDK do .NET, você pode criar um trabalho usando o novo comando de trabalho do dotnet. Se você estiver usando o Visual Studio, o modelo ficará oculto até que a carga de trabalho opcional de ASP.NET e desenvolvimento da Web seja instalada.
Terminologia
Muitos termos são usados erroneamente sinônimos. Esta seção define alguns desses termos para tornar a intenção deles neste artigo mais evidente.
Serviço de execução: qualquer serviço que seja executado continuamente.
Serviço Windows: a infraestrutura do Serviço Windows, originalmente centrada no .NET Framework, mas agora acessível por meio do .NET.
Serviço de trabalho: o modelo de Serviço de Trabalho.
Modelo de serviço de trabalho
O modelo de Serviço de Trabalho está disponível na CLI do .NET e no Visual Studio. Para obter mais informações, confira CLI do .NET – dotnet new workerModelo. O modelo consiste em uma classe Program e Worker.
Chama Run na instância host, que executa o aplicativo.
Padrões de modelo
O modelo de trabalho não habilita a coleta de lixo (GC) do servidor por padrão, pois há inúmeros fatores que desempenham um papel na determinação de sua necessidade. Todos os cenários que exigem serviços de execução longa devem considerar as implicações de desempenho desse padrão. Para habilitar o GC do servidor, adicione o nó ServerGarbageCollection ao arquivo de projeto:
Um aplicativo baseado no modelo de trabalho usa o SDK Microsoft.NET.Sdk.Worker e tem uma referência de pacote explícita ao pacote Microsoft.Extensions.Hosting.
Contêineres e adaptabilidade de nuvem
Com a maioria das cargas de trabalho modernas do .NET, os contêineres são uma opção viável. Ao criar um serviço de execução prolongada por meio do modelo de trabalho no Visual Studio, é possível aceitar o suporte do Docker. Fazer isso cria um Dockerfile que conteineriza seu aplicativo .NET. Um Dockerfile é um conjunto de instruções para compilar uma imagem. Para aplicativos .NET, o Dockerfile geralmente fica na raiz do diretório ao lado de um arquivo de solução.
# See https://aka.ms/containerfastmode to understand how Visual Studio uses this
# Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/runtime:8.0@sha256:e6b552fd7a0302e4db30661b16537f7efcdc0b67790a47dbf67a5e798582d3a5 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:8.0@sha256:35792ea4ad1db051981f62b313f1be3b46b1f45cadbaa3c288cd0d3056eefb83 AS build
WORKDIR /src
COPY ["background-service/App.WorkerService.csproj", "background-service/"]
RUN dotnet restore "background-service/App.WorkerService.csproj"
COPY . .
WORKDIR "/src/background-service"
RUN dotnet build "App.WorkerService.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "App.WorkerService.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "App.WorkerService.dll"]
As etapas anteriores do Dockerfile incluem:
Definir a imagem base de mcr.microsoft.com/dotnet/runtime:8.0 como o alias base.
Alterar o diretório de trabalho para /app.
Definir o alias build da imagem mcr.microsoft.com/dotnet/sdk:8.0.
Alterar o diretório de trabalho para /src.
Copiar conteúdos e publicar o aplicativo .NET:
O aplicativo é publicado usando o comando dotnet publish.
Retransmitir a imagem do SDK do .NET por meio de mcr.microsoft.com/dotnet/runtime:8.0 (alias base).
Copiar a saída de compilação publicada de /publish.
O MCR em mcr.microsoft.com significa "Registro de Contêiner da Microsoft" e é o catálogo de contêineres sindicalizado da Microsoft do hub oficial do Docker. O artigo do catálogo de contêineres dos sindicatos da Microsoft contém detalhes adicionais.
Quando você direciona o Docker como uma estratégia de implantação para o Serviço de Trabalho do .NET, há algumas considerações no arquivo de projeto:
No arquivo de projeto anterior, o elemento <DockerDefaultTargetOS> especifica Linux como seu destino. Para direcionar contêineres do Windows, use Windows. O pacote NuGet Microsoft.VisualStudio.Azure.Containers.Tools.Targets é adicionado automaticamente como uma referência de pacote quando o suporte do Docker é selecionado no modelo.
Para utilizar os segredos do usuário com o modelo de trabalho, é preciso fazer uma referência explícita ao pacote NuGet Microsoft.Extensions.Configuration.UserSecrets.
Esses dois métodos servem como métodos de ciclo de vida – são chamados durante eventos de início e parada do host, respectivamente.
Observação
Ao substituir os métodos StartAsync ou StopAsync, você deve chamar e await o método de classe base para garantir que o serviço seja iniciado e/ou desligado corretamente.
Importante
A interface serve como uma restrição de parâmetro de tipo genérico no método de extensão, o AddHostedService<THostedService>(IServiceCollection) que significa que apenas implementações são permitidas. Você é livre para usar o BackgroundService fornecido com uma subclasse ou implementar o seu do zero.
Sinalizar conclusão
Na maioria dos cenários comuns, você não precisa sinalizar explicitamente a conclusão de um serviço hospedado. Os serviços são projetados para serem executados desde quando o host os inicia até que o host seja interrompido. No entanto, em alguns cenários, pode ser necessário sinalizar a conclusão de todo o aplicativo host quando o serviço é concluído. Para sinalizar a conclusão, considere a seguinte classe Worker:
namespace App.SignalCompletionService;
public sealed class Worker(
IHostApplicationLifetime hostApplicationLifetime,
ILogger<Worker> logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// TODO: implement single execution logic here.
logger.LogInformation(
"Worker running at: {Time}", DateTimeOffset.Now);
await Task.Delay(1_000, stoppingToken);
// When completed, the entire app host will stop.
hostApplicationLifetime.StopApplication();
}
}
A fonte deste conteúdo pode ser encontrada no GitHub, onde você também pode criar e revisar problemas e solicitações de pull. Para obter mais informações, confira o nosso guia para colaboradores.
Comentários do .NET
O .NET é um projeto código aberto. Selecione um link para fornecer comentários:
Entenda e implemente a injeção de dependência em um aplicativo ASP.NET Core. Use o contêiner de serviço interno do ASP.NET Core para gerenciar dependências. Registre serviços com o contêiner de serviço.