IHostedService拡張メソッドのいずれかを使用してAddHostedServiceの実装を登録すると、サービスはシングルトンとして登録されます。 スコープ付きサービスに依存するシナリオが存在する場合があります。 詳細については、「 .NET の依存関係の挿入: サービスの有効期間」を参照してください。
このチュートリアルでは、以下の内容を学習します。
- シングルトン BackgroundServiceでスコープ付き依存関係を正しく解決します。
- スコープ付きサービスに作業を委任します。
-
override
のBackgroundService.StopAsync(CancellationToken)を実装します。
ヒント
すべての ".NET のワーカー" サンプル ソース コードは、 サンプル ブラウザー でダウンロードできます。 詳細については、「コードサンプルを閲覧: .NET のワーカー」を参照してください。
[前提条件]
- .NET 8.0 SDK 以降
- .NET 統合開発環境 (IDE)
- Visual Studio を自由に使用できます
新しいプロジェクトを作成する
Visual Studio で新しい Worker Service プロジェクトを作成するには、 ファイル>New>Project...を選択します。[ 新しいプロジェクトの作成 ] ダイアログで"Worker Service" を検索し、Worker Service テンプレートを選択します。 .NET CLI を使用する場合は、作業ディレクトリでお気に入りのターミナルを開きます。
dotnet new
コマンドを実行し、<Project.Name>
を目的のプロジェクト名に置き換えます。
dotnet new worker --name <Project.Name>
.NET CLI の新しい worker サービス プロジェクト コマンドの詳細については、「 dotnet new worker」を参照してください。
ヒント
Visual Studio Code を使用している場合は、統合ターミナルから .NET CLI コマンドを実行できます。 詳細については、「 Visual Studio Code: 統合ターミナル」を参照してください。
スコープ付きサービスを作成する
内でBackgroundService
を使用するには、IServiceScopeFactory.CreateScope() API を使用してスコープを作成します。 既定では、ホステッド サービスのスコープは作成されません。 スコープ付きバックグラウンド サービスには、バックグラウンド タスクのロジックが含まれています。
namespace App.ScopedService;
public interface IScopedProcessingService
{
Task DoWorkAsync(CancellationToken stoppingToken);
}
上記のインターフェイスは、1 つの DoWorkAsync
メソッドを定義します。 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は、プライマリ コンストラクターを使用してサービスに挿入されます。
-
DoWorkAsync
メソッドはTask
を返し、CancellationTokenを受け入れます。- このメソッドはインスタンス識別子をログに記録します。
_instanceId
は、クラスがインスタンス化されるたびに割り当てられます。
- このメソッドはインスタンス識別子をログに記録します。
Worker クラスを書き換える
既存の Worker
クラスを次の C# コードに置き換え、ファイルの名前を 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);
}
}
上記のコードでは、 stoppingToken
は取り消されませんが、スコープの作成には IServiceScopeFactory
が使用されます。
IServiceScope
から、IScopedProcessingService
が解決されます。
DoWorkAsync
メソッドが待機され、stoppingToken
がメソッドに渡されます。 最後に、実行が 10 秒間遅延され、ループが続行されます。
DoWorkAsync
メソッドが呼び出されるたびに、DefaultScopedProcessingService
の新しいインスタンスが作成され、インスタンス識別子がログに記録されます。
テンプレートProgram.csファイル の 内容を次の C# コードに置き換えます。
using App.ScopedService;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<ScopedBackgroundService>();
builder.Services.AddScoped<IScopedProcessingService, DefaultScopedProcessingService>();
IHost host = builder.Build();
host.Run();
サービスは (Program.cs) に登録されます。 ホステッド サービスは、 AddHostedService 拡張メソッドに登録されます。
サービスの登録の詳細については、「 .NET での依存関係の挿入」を参照してください。
サービス機能を確認する
Visual Studio からアプリケーションを実行するには、 F5 キーを押すか、[ デバッグ>デバッグの開始 ] メニュー オプションを選択します。 .NET CLI を使用している場合は、作業ディレクトリから dotnet run
コマンドを実行します。
dotnet run
.NET CLI 実行コマンドの詳細については、「 dotnet run」を参照してください。
アプリケーションを少し実行して、 DoWorkAsync
の呼び出しをいくつか生成し、新しいインスタンス識別子をログに記録します。 次のログのような出力が表示されます。
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.
Visual Studio 内からアプリケーションを実行する場合は、[ デバッグ>ストップ デバッグ...] を選択します。または、コンソール ウィンドウから Ctrl + C を選択してキャンセルを通知します。
こちらも参照ください
.NET