Compartir a través de


Uso de servicios delimitados dentro de BackgroundService

Al registrar implementaciones de IHostedService usando cualquiera de los métodos de extensión de AddHostedService, el servicio se registra como singleton. Puede haber escenarios en los que le gustaría depender de un servicio definido por ámbito. Para obtener más información, consulte Inserción de dependencias en .NET: Duración del servicio.

En este tutorial, aprenderá a:

Sugerencia

Todo el código fuente de ejemplo de "Workers in .NET" está disponible en el Explorador de Muestras para su descarga. Para obtener más información, consulte Examinación de ejemplos de código: Trabajos en .NET.

Prerrequisitos

Creación de un nuevo proyecto

Para crear un proyecto de Worker Service con Visual Studio, seleccione Archivo>Nuevo>Proyecto... . En el cuadro de diálogo Crear un proyecto, busque "Worker Service" y seleccione la plantilla Worker Service. Si prefiere usar la CLI de .NET, abra su terminal favorito en un directorio de trabajo. Ejecute el comando dotnet new y reemplace el <Project.Name> por el nombre del proyecto deseado.

dotnet new worker --name <Project.Name>

Para más información sobre el comando del nuevo proyecto de Worker Service de la CLI de .NET, vea dotnet new worker.

Sugerencia

Si usa Visual Studio Code, puede ejecutar comandos de la CLI de .NET desde el terminal integrado. Para obtener más información, vea Visual Studio Code: Terminal integrado.

Servicios con ámbito definido

Para usar servicios con ámbito dentro de un BackgroundService, cree un ámbito con la IServiceScopeFactory.CreateScope() API. No se crean ámbitos de forma predeterminada para los servicios hospedados. El servicio en segundo plano con un alcance definido contiene la lógica de la tarea en segundo plano.

namespace App.ScopedService;

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

La interfaz anterior define un único DoWorkAsync método. Cree una implementación en una nueva clase denominada DefaultScopedProcessingService.cs:

namespace App.ScopedService;

public sealed class DefaultScopedProcessingService(
    ILogger<DefaultScopedProcessingService> logger) : IScopedProcessingService
{
    private readonly string _instanceId = Guid.NewGuid().ToString();

    public Task DoWorkAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{ServiceName} doing work, instance ID: {Id}",
            nameof(DefaultScopedProcessingService),
            _instanceId);

        return Task.CompletedTask;
    }
}
  • ILogger se inyecta en el servicio mediante un constructor principal.
  • El método DoWorkAsync devuelve un Task y acepta el CancellationToken.
    • El método registra el identificador de instancia: _instanceId se asigna cada vez que se crea una instancia de la clase.

Reescritura de la clase Worker

Reemplace la clase existente Worker por el siguiente código de C# y cambie el nombre del archivo a 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);

        while (!stoppingToken.IsCancellationRequested)
        {
            using IServiceScope scope = serviceScopeFactory.CreateScope();

            IScopedProcessingService scopedProcessingService =
                scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();

            await scopedProcessingService.DoWorkAsync(stoppingToken);

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

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

        await base.StopAsync(stoppingToken);
    }
}

En el código anterior, mientras stoppingToken no se cancela, IServiceScopeFactory se usa para crear un ámbito. Desde el IServiceScope, se resuelve el IScopedProcessingService. Se espera el DoWorkAsync método y stoppingToken se pasa al método . Por último, la ejecución se retrasa durante 10 segundos y el bucle continúa. Cada vez que se llama al DoWorkAsync método , se crea una nueva instancia de DefaultScopedProcessingService y se registra el identificador de instancia.

Reemplace la plantilla Program.cs contenido del archivo por el siguiente código de C#:

using App.ScopedService;

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

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

Los servicios se registran en (Program.cs). El servicio hospedado se registra con el método de extensión AddHostedService.

Para obtener más información sobre el registro de servicios, consulte Inserción de dependencias en .NET.

Comprobación de la funcionalidad del servicio

Para ejecutar la aplicación desde Visual Studio, seleccione F5 o seleccione la opción de menú Iniciar depuración>. Si usa la CLI de .NET, ejecute el dotnet run comando desde el directorio de trabajo:

dotnet run

Para más información sobre el comando run de la CLI de .NET, consulte dotnet run.

Permitir que la aplicación se ejecute un poco para generar varias llamadas a DoWorkAsync, registrando así nuevos identificadores de instancia. Verá una salida similar a los registros siguientes:

info: App.ScopedService.ScopedBackgroundService[0]
      ScopedBackgroundService is running.
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService doing work, instance ID: 8986a86f-b444-4139-b9ea-587daae4a6dd
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 doing work, instance ID: 07a4a760-8e5a-4c0a-9e73-fcb2f93157d3
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService doing work, instance ID: c847f432-acca-47ee-8720-1030859ce354
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: App.ScopedService.ScopedBackgroundService[0]
      ScopedBackgroundService is stopping.

Si ejecuta la aplicación desde Visual Studio, seleccione Depurar>.... Como alternativa, seleccione Ctrl + C en la ventana de la consola para indicar la cancelación.

Consulte también