.NET Generic Host 入門

· · C#, .NET, Generic Host, Worker, 設計

結論

Generic Host は、.NETアプリの起動と有効期間(ライフタイム)をまとめて扱う土台です。DI(依存性注入)、設定、ログ、バックグラウンド処理、アプリの停止処理をひとまとめに管理します。

  • 新しい非Webアプリでは Host.CreateApplicationBuilder(args) から始める
  • ASP.NET Coreの WebApplicationBuilder も同じ考え方の上にWeb機能を追加したもの
  • 短命なジョブにまで毎回使う必要はない(小さなツールなら不要)

Generic Hostが提供するもの

機能 内容 メリット
DI IServiceCollection からサービスを組み立て new の連鎖を減らせる
設定 appsettings.json、環境変数、コマンドライン引数を統合 環境ごとの差分を扱いやすい
ログ ILogger<T> の基盤を提供 出力先を後から差し替えやすい
Hosted Service IHostedService/BackgroundService の起動と停止 常駐処理をアプリ本体と分離
ライフタイム 開始・停止の管理(Ctrl+C、SIGTERM対応) 終了処理を統一できる

Builderの違い

エントリポイント 主な用途 いつ使うか
Host.CreateApplicationBuilder(args) コンソール/worker(新規) 新しい非Webアプリならこれ
Host.CreateDefaultBuilder(args) コンソール/worker(既存) 既存の拡張メソッド主体のコード
WebApplication.CreateBuilder(args) ASP.NET Core Web/API Webアプリならこれ

CreateApplicationBuilderCreateDefaultBuilder は書き方の流儀が違うだけで、コア機能は同じです。新規なら CreateApplicationBuilder が素直です。

処理の流れ

args/環境変数/appsettings.json
    ↓
Host.CreateApplicationBuilder(args)
    ↓
builder.Configuration / builder.Services / builder.Logging
    ↓
builder.Services にサービスや BackgroundService を登録
    ↓
builder.Build() → IHost を取得
    ↓
Run() / RunAsync() → 起動・停止・Ctrl+C・SIGTERMを管理

既定で以下のものが自動的に組み込まれます:

  • appsettings.jsonappsettings.{Environment}.json、環境変数、コマンドライン引数
  • Console、Debug、EventSource、EventLog(Windowsのみ)へのログ出力
  • Development環境でのscope検証と依存関係検証

最小構成:短命なコンソールツール

using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddSingleton<JobRunner>();

using IHost host = builder.Build();

JobRunner runner = host.Services.GetRequiredService<JobRunner>();
await runner.RunAsync();

1回だけ仕事をして終わるアプリでも、設定・ログ・DIが欲しければGeneric Hostは十分使えます。BackgroundServiceの作成は必須ではありません。

常駐処理:BackgroundServiceの使い方

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddScoped<PollingJob>();
builder.Services.AddHostedService<PollingWorker>();

using IHost host = builder.Build();
await host.RunAsync();

internal sealed class PollingWorker(
    IServiceScopeFactory scopeFactory,
    ILogger<PollingWorker> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using PeriodicTimer timer = new(TimeSpan.FromSeconds(30));

        while (await timer.WaitForNextTickAsync(stoppingToken))
        {
            using IServiceScope scope = scopeFactory.CreateScope();
            PollingJob job = scope.ServiceProvider.GetRequiredService<PollingJob>();
            await job.RunAsync(stoppingToken);
        }
    }
}

重要ポイント

  • BackgroundService には既定のスコープがない
  • scopedサービス(DbContext など)を使う場合は IServiceScopeFactory で明示的にスコープを作成
  • 仕事が終わったら IHostApplicationLifetime.StopApplication() でホストに停止を通知

向いているケース

  • 設定・ログ・DIを使うコンソールアプリ
  • キュー消費者、ポーラー、ウォッチドッグなどの常駐worker
  • Ctrl+CやSIGTERMで後片付けしたい長時間実行アプリ
  • 将来的にWindows Serviceやコンテナ常駐へ成長する可能性があるアプリ
  • ASP.NET Coreと同じ流儀に揃えたい

向かない/過剰なケース

  • 引数を1回読んで1回出力して終わる小さなツール
  • 数十分だけ使う検証コード
  • ライブラリプロジェクト
  • 設定を1つ読むだけでDIやログやライフタイム管理が不要な場合

はまりやすいポイント

  1. Generic HostをDIコンテナだけだと思う — 実際は起動・停止・設定・ログを含む土台
  2. 新規アプリなのに Host.CreateDefaultBuilder から始める — 新規なら CreateApplicationBuilder のほうが素直
  3. BackgroundService にscopedサービスを直接注入する — 明示的にスコープを作成する
  4. 1回だけの処理なのに BackgroundService で囲う — 普通のサービスクラスを解決して実行すれば十分
  5. Environment.Exit で強制終了するStopApplication() のほうがきれいに止まる
  6. Windows Serviceでカレントディレクトリ前提にするIHostEnvironment.ContentRootPath を基準にする
  7. 定期実行にcallbackタイマーを雑に入れるasync ベースなら PeriodicTimer のほうが安全

まとめ

Generic Hostは重たい儀式のための道具ではありません。設定・ログ・依存関係・起動・終了が増えてきたら、それらをまとめて管理するための土台です。

  1. Generic HostはDIだけでなく、設定・ログ・停止処理・hosted serviceを含む
  2. 新規非Webアプリなら Host.CreateApplicationBuilder(args) が素直
  3. 短命ジョブなら BackgroundService なしでも使える
  4. 常駐処理なら BackgroundService + hostのライフタイム管理が効く
  5. scopedサービスは明示的にスコープを作成する
  6. ASP.NET Coreの WebApplicationBuilder も同じ流れの上にある

関連する記事

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

FileSystemWatcherの安全な使い方

FileSystemWatcher のイベントは完了通知ではないという前提に立ち、取りこぼし、重複通知、完了判定の落とし穴を整理し、再スキャン要求への畳み込み、原子的 claim、idempotency までの設計指針をまとめます。

記事を読む

関連トピック

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

このテーマがつながるサービス

この記事は次のサービスページにつながります。近い入口からご覧ください。

ブログ一覧に戻る