Scoped services binnen een BackgroundService

Wanneer u implementaties registreert van IHostedService het gebruik van een van de AddHostedService extensiemethoden, wordt de service geregistreerd als een singleton. Er kunnen scenario's zijn waarin u afhankelijk wilt zijn van een scoped service. Zie Afhankelijkheidsinjectie in .NET: Levensduur van de service voor meer informatie.

In deze zelfstudie leert u het volgende:

Tip

Alle voorbeeldbroncode 'Workers in .NET' is beschikbaar in de voorbeeldenbrowser om te downloaden. Zie Codevoorbeelden bekijken: Workers in .NET voor meer informatie.

Vereisten

  • De .NET 8.0 SDK of hoger
  • Een .NET Integrated Development Environment (IDE)
    • U kunt Visual Studio gerust gebruiken

Een nieuw project maken

Als u een nieuw Worker Service-project wilt maken met Visual Studio, selecteert u Bestand>nieuw>project.... Zoek in het dialoogvenster Een nieuw project maken naar 'Worker Service' en selecteer de sjabloon Worker Service. Als u liever de .NET CLI gebruikt, opent u uw favoriete terminal in een werkmap. Voer de dotnet new opdracht uit en vervang de door de <Project.Name> gewenste projectnaam.

dotnet new worker --name <Project.Name>

Zie dotnet new worker voor meer informatie over de opdracht .NET CLI new worker service project.

Tip

Als u Visual Studio Code gebruikt, kunt u .NET CLI-opdrachten uitvoeren vanuit de geïntegreerde terminal. Zie Visual Studio Code: Integrated Terminal voor meer informatie.

Bereikservices maken

Als u scoped services binnen een BackgroundServicebereik wilt gebruiken, maakt u een bereik. Er wordt standaard geen bereik gemaakt voor een gehoste service. De scoped background-service bevat de logica van de achtergrondtaak.

namespace App.ScopedService;

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

De voorgaande interface definieert één DoWorkAsync methode. De standaard implementatie definiëren:

  • De service is asynchroon. De DoWorkAsync methode retourneert een Task. Voor demonstratiedoeleinden wordt een vertraging van tien seconden in de DoWorkAsync methode verwacht.
  • Er ILogger wordt een in de service geïnjecteerd.:
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);
        }
    }
}

De gehoste service maakt een bereik om de scoped achtergrondservice om de methode aan te roepen DoWorkAsync . DoWorkAsync geeft als resultaat een Task, die in het ExecuteAsyncvolgende wordt gewacht:

De werkrolklasse herschrijven

Vervang de bestaande Worker klasse door de volgende C#-code en wijzig de naam van het bestand 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);

        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);
    }
}

In de voorgaande code wordt een expliciet bereik gemaakt en wordt de IScopedProcessingService implementatie omgezet vanuit de factory voor het bereik van de afhankelijkheidsinjectieservice. Het opgeloste service-exemplaar is binnen het bereik en DoWorkAsync de bijbehorende methode wordt verwacht.

Vervang de inhoud van het bestand template Program.cs door de volgende C#-code:

using App.ScopedService;

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

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

De services worden geregistreerd in (Program.cs). De gehoste service wordt geregistreerd bij de AddHostedService extensiemethode.

Zie Afhankelijkheidsinjectie in .NET voor meer informatie over het registreren van services.

Servicefunctionaliteit controleren

Als u de toepassing vanuit Visual Studio wilt uitvoeren, selecteert u F5 of selecteert u de menuoptie Foutopsporing> starten. Als u de .NET CLI gebruikt, voert u de dotnet run opdracht uit vanuit de werkmap:

dotnet run

Zie dotnet run voor meer informatie over de .NET CLI-run-opdracht.

Laat de toepassing een beetje uitvoeren om verschillende stappen voor het aantal uitvoeringen te genereren. De uitvoer ziet er ongeveer als volgt uit:

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.

Als u de toepassing vanuit Visual Studio uitvoert, selecteert u Foutopsporing>stoppen.... U kunt ook Ctrl + C selecteren in het consolevenster om annulering te signaleren.

Zie ook