BackgroundService
内でスコープ付きサービスを使用する
AddHostedService 拡張メソッドのいずれかを使用して IHostedService の実装を登録すると、サービスはシングルトンとして登録されます。 スコープ付きサービスに依存したいシナリオがある場合があります。 詳細については、.NET での依存関係の挿入のサービスの有効期間に関する記事を参照してください。
このチュートリアルでは、次の作業を行う方法について説明します。
- シングルトン BackgroundService 内のスコープ付き依存関係を解決します。
- スコープ付きサービスに作業を委任します。
- BackgroundService.StopAsync(CancellationToken)の
override
を実装します。
ヒント
".NET でのワーカー" のサンプル ソース コードはすべて、サンプル ブラウザーでダウンロードできます。 詳細については、コード サンプルの参照: .NET でのワーカーに関するページをご覧ください。
前提条件
- .NET 8.0 SDK 以降
- .NET 統合開発環境 (IDE)
- Visual Studio を自由に使用できます
新しいプロジェクトを作る
Visual Studio を使用して新しい Worker サービス プロジェクトを作成するには、[ファイル]>[新規]>[プロジェクト] を選択します。[新しいプロジェクトの作成] ダイアログで "Worker サービス" を検索し、Worker サービス テンプレートを選択します。 .NET CLI を使用する場合は、作業ディレクトリで好みのターミナルを開きます。 dotnet new
コマンドを実行し、<Project.Name>
を目的のプロジェクト名に置き換えます。
dotnet new worker --name <Project.Name>
.NET CLI の new worker サービス プロジェクト コマンドの詳細については、「dotnet new worker」を参照してください。
ヒント
Visual Studio Code を使用している場合は、統合ターミナルから .NET CLI コマンドを実行できます。 詳細については、Visual Studio Code の統合ターミナルに関する記事を参照してください。
スコープ付きサービスを作成する
BackgroundService
内でスコープ サービスを使用するには、スコープを作成します。 既定では、ホステッド サービスのスコープは作成されません。 スコープ付きバックグラウンド サービスには、バックグラウンド タスクのロジックが含まれています。
namespace App.ScopedService;
public interface IScopedProcessingService
{
Task DoWorkAsync(CancellationToken stoppingToken);
}
前のインターフェイスでは、1 つの DoWorkAsync
メソッドが定義されています。 既定の実装を定義するには:
- サービスは非同期です。
DoWorkAsync
メソッドはTask
を返します。 デモンストレーションのために、10 秒の遅延がDoWorkAsync
メソッドで待機されます。 - ILogger がサービスに挿入されます。
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);
}
}
}
ホステッド サービスにより、スコープ付きバックグラウンド サービスをその DoWorkAsync
メソッドの呼び出しに解決するためのスコープが作成されます。 ExecuteAsync
で待機していた DoWorkAsync
が Task
を返します。
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);
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);
}
}
前のコードでは、明示的なスコープが作成され、IScopedProcessingService
の実装が依存関係挿入サービス スコープ ファクトリから解決されます。 解決されたサービス インスタンスにはスコープが設定されており、その DoWorkAsync
メソッドが待機されています。
テンプレートの 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 の run コマンドの詳細については、「dotnet run」を参照してください。
アプリケーションをしばらく実行させて、何回か実行カウントのインクリメントを生成します。 次のような出力が表示されます。
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.
Visual Studio 内からアプリケーションを実行している場合は、[デバッグ]>[デバッグの停止] を選択します。または、コンソール ウィンドウで Ctrl + C キーを押して、キャンセルを通知します。
関連項目
.NET