Condividi tramite


Usare i servizi limitati all'interno di un BackgroundService

Quando si registrano le implementazioni di IHostedService usando uno dei AddHostedService metodi di estensione, il servizio viene registrato come singleton. Potrebbero esserci scenari in cui si vuole fare affidamento su un servizio con ambito. Per maggiori informazioni, vedere Iniezione delle dipendenze in .NET: Gestione dei cicli di vita dei servizi.

In questa esercitazione si apprenderà come:

Suggerimento

Tutto il codice sorgente di esempio "Workers in .NET" è disponibile nel Samples Browser per il download. Per ulteriori informazioni, consulta Esempi di codice: Workers in .NET.

Prerequisiti

Creare un nuovo progetto

Per creare un nuovo progetto del servizio di lavoro con Visual Studio, selezionare File>Nuovo progetto>. Nella finestra di dialogo Crea un nuovo progetto cercare "Servizio di lavoro" e selezionare Modello servizio di lavoro. Se si preferisce usare l'interfaccia della riga di comando di .NET, aprire il terminale preferito in una directory di lavoro. Eseguire il comando dotnet new e sostituire il <Project.Name> con il nome del progetto desiderato.

dotnet new worker --name <Project.Name>

Per ulteriori informazioni sul comando del progetto new worker service di .NET CLI, vedere dotnet new worker.

Suggerimento

Se si usa Visual Studio Code, è possibile eseguire i comandi dell'interfaccia della riga di comando di .NET dal terminale integrato. Per altre informazioni, vedere Visual Studio Code: Integrated Terminal.

Creare servizi con ambito definito

Per usare i servizi con ambito all'interno di unBackgroundService, creare un ambito con l'API IServiceScopeFactory.CreateScope(). Non viene creato automaticamente alcun ambito per un servizio ospitato. Il servizio con ambito nel background contiene la logica dell'attività in background.

namespace App.ScopedService;

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

L'interfaccia precedente definisce un singolo DoWorkAsync metodo. Creare un'implementazione in una nuova classe denominata 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;
    }
}
  • Un ILogger oggetto viene inserito nel servizio usando un costruttore primario.
  • Il metodo DoWorkAsync restituisce un Task e accetta il CancellationToken.
    • Il metodo registra l'identificatore dell'istanza, che _instanceId viene assegnato ogni volta che viene creata un'istanza della classe.

Riscrivere la classe Worker

Sostituire la classe esistente Worker con il codice C# seguente e rinominare il file in 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);
    }
}

Nel codice precedente, mentre l'oggetto stoppingToken non viene annullato, IServiceScopeFactory viene usato per creare un ambito. Dallo IServiceScope, il IScopedProcessingService viene risolto. Il metodo DoWorkAsync è atteso e stoppingToken viene passato al metodo. Infine, l'esecuzione viene ritardata per 10 secondi e il ciclo continua. Ogni volta che viene chiamato il DoWorkAsync metodo, viene creata una nuova istanza di DefaultScopedProcessingService e viene registrato l'identificatore dell'istanza.

Sostituire il modello Program.cs contenuto del file con il codice C# seguente:

using App.ScopedService;

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

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

I servizi vengono registrati in (Program.cs). Il servizio ospitato viene registrato con il AddHostedService metodo di estensione.

Per ulteriori informazioni sulla registrazione dei servizi, vedere iniezione delle dipendenze in .NET.

Verificare la funzionalità del servizio

Per eseguire l'applicazione da Visual Studio, selezionare F5 o selezionare l'opzione di menu Debug>Avvia debug . Se stai usando l'interfaccia della riga di comando di .NET, esegui il comando dotnet run dalla directory di lavoro.

dotnet run

Per ulteriori informazioni sul comando di esecuzione della CLI di .NET, vedere dotnet run.

Lasciare che l'applicazione venga eseguita per un po' per generare diverse chiamate a DoWorkAsync, registrando così nuovi identificatori di istanza. Viene visualizzato un output simile ai log seguenti:

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.

Se si esegue l'applicazione da Visual Studio, selezionare Debug>Arresta debug.... In alternativa, selezionare CTRL + C dalla finestra della console per segnalare l'annullamento.

Vedere anche