Korzystanie z usług o określonym zakresie w obrębie BackgroundService
Podczas rejestrowania IHostedService implementacji przy użyciu dowolnej z AddHostedService metod rozszerzeń usługa jest zarejestrowana jako pojedyncza. Mogą istnieć scenariusze, w których chcesz polegać na usłudze o określonym zakresie. Aby uzyskać więcej informacji, zobacz Wstrzykiwanie zależności na platformie .NET: okresy istnienia usługi.
Ten samouczek zawiera informacje na temat wykonywania następujących czynności:
- Rozwiąż problemy z zależnościami o określonym zakresie w pojedynczym elemencie BackgroundService.
- Delegowanie pracy do usługi o określonym zakresie.
- Zaimplementuj BackgroundService.StopAsync(CancellationToken)element
override
.
Porada
Cały przykładowy kod źródłowy "Pracownicy na platformie .NET" jest dostępny w przeglądarce Samples Browser do pobrania. Aby uzyskać więcej informacji, zobacz Przeglądanie przykładów kodu: Procesy robocze na platformie .NET.
Wymagania wstępne
- Zestaw SDK platformy .NET 7.0 lub nowszy
- Zintegrowane środowisko projektowe (IDE) platformy .NET
- Możesz bezpłatnie korzystać z programu Visual Studio
- Zestaw SDK platformy .NET 6.0 lub nowszy
- Zintegrowane środowisko projektowe (IDE) platformy .NET
- Możesz bezpłatnie korzystać z programu Visual Studio
Tworzenie nowego projektu
Aby utworzyć nowy projekt usługi procesu roboczego za pomocą programu Visual Studio, wybierz pozycję Plik>nowy>projekt.... W oknie dialogowym Tworzenie nowego projektu wyszukaj frazę "Usługa procesu roboczego", a następnie wybierz pozycję Szablon usługi procesu roboczego. Jeśli chcesz użyć interfejsu wiersza polecenia platformy .NET, otwórz swój ulubiony terminal w katalogu roboczym. dotnet new
Uruchom polecenie i zastąp <Project.Name>
element odpowiednią nazwą projektu.
dotnet new worker --name <Project.Name>
Aby uzyskać więcej informacji na temat polecenia nowego projektu usługi procesu roboczego interfejsu wiersza polecenia platformy .NET, zobacz dotnet new worker (dotnet new worker).
Porada
Jeśli używasz Visual Studio Code, możesz uruchamiać polecenia interfejsu wiersza polecenia platformy .NET z poziomu zintegrowanego terminalu. Aby uzyskać więcej informacji, zobacz Visual Studio Code: Zintegrowany terminal.
Tworzenie usług o określonym zakresie
Aby użyć usług o określonym zakresie w ramach elementu BackgroundService
, utwórz zakres. Domyślnie dla hostowanej usługi nie jest tworzony żaden zakres. Usługa w tle o określonym zakresie zawiera logikę zadania w tle.
namespace App.ScopedService;
public interface IScopedProcessingService
{
Task DoWorkAsync(CancellationToken stoppingToken);
}
namespace App.ScopedService;
public interface IScopedProcessingService
{
Task DoWorkAsync(CancellationToken stoppingToken);
}
Powyższy interfejs definiuje jedną DoWorkAsync
metodę. Aby zdefiniować implementację domyślną:
- Usługa jest asynchroniczna. Metoda
DoWorkAsync
zwraca wartośćTask
. W celach demonstracyjnych oczekuje się opóźnienia dziesięciu sekund w metodzieDoWorkAsync
. - Element ILogger jest wstrzykiwany do usługi.:
namespace App.ScopedService;
public sealed class DefaultScopedProcessingService : IScopedProcessingService
{
private int _executionCount;
private readonly ILogger<DefaultScopedProcessingService> _logger;
public DefaultScopedProcessingService(
ILogger<DefaultScopedProcessingService> logger) =>
_logger = logger;
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);
}
}
}
namespace App.ScopedService;
public sealed class DefaultScopedProcessingService : IScopedProcessingService
{
private int _executionCount;
private readonly ILogger<DefaultScopedProcessingService> _logger;
public DefaultScopedProcessingService(
ILogger<DefaultScopedProcessingService> logger) =>
_logger = logger;
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);
}
}
}
Usługa hostowana tworzy zakres, aby rozwiązać problem z usługą w tle o określonym zakresie w celu wywołania metody DoWorkAsync
. DoWorkAsync
zwraca element , który jest oczekiwany w elemecie Task
ExecuteAsync
:
Ponowne zapisywanie klasy Worker
Zastąp istniejącą Worker
klasę następującym kodem języka C# i zmień nazwę pliku na ScopedBackgroundService.cs:
namespace App.ScopedService;
public sealed class ScopedBackgroundService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<ScopedBackgroundService> _logger;
public ScopedBackgroundService(
IServiceProvider serviceProvider,
ILogger<ScopedBackgroundService> logger) =>
(_serviceProvider, _logger) = (serviceProvider, logger);
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
$"{nameof(ScopedBackgroundService)} is running.");
await DoWorkAsync(stoppingToken);
}
private async Task DoWorkAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
$"{nameof(ScopedBackgroundService)} is working.");
using (IServiceScope scope = _serviceProvider.CreateScope())
{
IScopedProcessingService scopedProcessingService =
scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();
await scopedProcessingService.DoWorkAsync(stoppingToken);
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
$"{nameof(ScopedBackgroundService)} is stopping.");
await base.StopAsync(stoppingToken);
}
}
namespace App.ScopedService;
public sealed class ScopedBackgroundService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<ScopedBackgroundService> _logger;
public ScopedBackgroundService(
IServiceProvider serviceProvider,
ILogger<ScopedBackgroundService> logger) =>
(_serviceProvider, _logger) = (serviceProvider, logger);
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
$"{nameof(ScopedBackgroundService)} is running.");
await DoWorkAsync(stoppingToken);
}
private async Task DoWorkAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
$"{nameof(ScopedBackgroundService)} is working.");
using (IServiceScope scope = _serviceProvider.CreateScope())
{
IScopedProcessingService scopedProcessingService =
scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();
await scopedProcessingService.DoWorkAsync(stoppingToken);
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
$"{nameof(ScopedBackgroundService)} is stopping.");
await base.StopAsync(stoppingToken);
}
}
W poprzednim kodzie tworzony jest jawny zakres, a implementacja IScopedProcessingService
jest rozpoznawana przez dostawcę usługi iniekcji zależności. Rozpoznane wystąpienie usługi ma zakres, a jego DoWorkAsync
metoda jest oczekiwana.
Zastąp zawartość pliku Template Program.cs następującym kodem w języku C#:
using App.ScopedService;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<ScopedBackgroundService>();
builder.Services.AddScoped<IScopedProcessingService, DefaultScopedProcessingService>();
IHost host = builder.Build();
host.Run();
using App.ScopedService;
IHostBuilder builder = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<ScopedBackgroundService>();
services.AddScoped<IScopedProcessingService, DefaultScopedProcessingService>();
});
IHost host = builder.Build();
host.Run();
Usługi są rejestrowane w pliku (Program.cs). Hostowana usługa jest zarejestrowana w metodzie AddHostedService
rozszerzenia.
Aby uzyskać więcej informacji na temat rejestrowania usług, zobacz Wstrzykiwanie zależności na platformie .NET.
Weryfikowanie funkcjonalności usługi
Aby uruchomić aplikację z programu Visual Studio, wybierz pozycję F5 lub wybierz opcję menu Debuguj>rozpocznij debugowanie . Jeśli używasz interfejsu wiersza polecenia platformy .NET, uruchom dotnet run
polecenie z katalogu roboczego:
dotnet run
Aby uzyskać więcej informacji na temat polecenia uruchamiania interfejsu wiersza polecenia platformy .NET, zobacz dotnet run.
Niech aplikacja będzie uruchamiana na nieco, aby wygenerować kilka przyrostów liczby wykonań. Zostaną wyświetlone dane wyjściowe podobne do następujących:
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.
W przypadku uruchamiania aplikacji z poziomu programu Visual Studio wybierz pozycję Debuguj zatrzymaj debugowanie>.... Alternatywnie wybierz klawisze Ctrl + C w oknie konsoli, aby zasygnalizować anulowanie.
Zobacz też
.NET feedback
The .NET documentation is open source. Provide feedback here.
Opinia
Prześlij i wyświetl opinię dla