IHostedService 인터페이스 구현

제공된 BackgroundService를 초과하는 유한 제어가 필요한 경우 사용자 고유의 IHostedService를 구현할 수 있습니다. IHostedService 인터페이스는 .NET의 모든 장기 실행 서비스에 대한 기본입니다. 사용자 지정 구현은 AddHostedService<THostedService>(IServiceCollection) 확장 메서드를 사용하여 등록됩니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • IHostedServiceIAsyncDisposable 인터페이스를 구현합니다.
  • 타이머 기반 서비스를 만듭니다.
  • 종속성 주입 및 로깅을 사용하여 사용자 지정 구현을 등록합니다.

모든 ‘.NET의 작업자’ 예제 소스 코드는 샘플 브라우저에서 다운로드할 수 있습니다. 자세한 내용은 코드 샘플 찾아보기: .NET의 작업자를 참조하세요.

필수 조건

새 프로젝트 만들기

Visual Studio를 사용하여 새 Worker Service 프로젝트를 만들려면 파일>새로 만들기>Project...를 선택합니다. 새 프로젝트 만들기 대화 상자에서 "Worker Service"를 검색하고 Worker Service 템플릿을 선택합니다. .NET CLI를 사용하려면 작업 디렉터리에서 즐겨찾는 터미널을 엽니다. dotnet new 명령을 실행하고 <Project.Name>을 원하는 프로젝트 이름으로 바꿉니다.

dotnet new worker --name <Project.Name>

.NET CLI 새 작업자 서비스 프로젝트 명령에 대한 자세한 내용은 dotnet 새 작업자를 참조하세요.

Visual Studio Code를 사용하는 경우 통합 터미널에서 .NET CLI 명령을 실행할 수 있습니다. 자세한 내용은 Visual Studio Code: 통합 터미널을 참조하세요.

타이머 서비스 만들기

타이머 기반 백그라운드 서비스는 System.Threading.Timer 클래스를 사용합니다. 타이머가 DoWork 메서드를 트리거합니다. 서비스 컨테이너가 IAsyncDisposable.DisposeAsync()에서 삭제될 때 IHostLifetime.StopAsync(CancellationToken)에서 타이머가 비활성화되고 삭제됩니다.

다음 C# 코드를 사용하여 템플릿에서 Worker의 콘텐츠를 바꾸고, 파일의 이름을 TimerService.cs로 바꿉니다.

namespace App.TimerHostedService;

public sealed class TimerService(ILogger<TimerService> logger) : IHostedService, IAsyncDisposable
{
    private readonly Task _completedTask = Task.CompletedTask;
    private int _executionCount = 0;
    private Timer? _timer;

    public Task StartAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation("{Service} is running.", nameof(TimerHostedService));
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

        return _completedTask;
    }

    private void DoWork(object? state)
    {
        int count = Interlocked.Increment(ref _executionCount);

        logger.LogInformation(
            "{Service} is working, execution count: {Count:#,0}",
            nameof(TimerHostedService),
            count);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Service} is stopping.", nameof(TimerHostedService));

        _timer?.Change(Timeout.Infinite, 0);

        return _completedTask;
    }

    public async ValueTask DisposeAsync()
    {
        if (_timer is IAsyncDisposable timer)
        {
            await timer.DisposeAsync();
        }

        _timer = null;
    }
}

Important

WorkerBackgroundService의 하위 클래스입니다. 이제 TimerServiceIHostedServiceIAsyncDisposable 인터페이스를 둘 다 구현합니다.

TimerServicesealed이며 해당 _timer 인스턴스에서 DisposeAsync 호출을 계단식으로 배열합니다. "연계 Dispose 패턴"에 대한 자세한 내용은 DisposeAsync 메서드 구현을 참조하세요.

StartAsync가 호출되면 타이머가 인스턴스화되어 타이머가 시작됩니다.

Timer는 이전에 실행된 DoWork를 마칠 때까지 기다리지 않으므로 제시된 방법이 모든 시나리오에 적합한 것은 아닐 수 있습니다. Interlocked.Increment는 여러 스레드가 동시에 _executionCount를 업데이트하지 않도록 하는 원자성 작업으로 실행 카운터를 증가시키는 데 사용됩니다.

기존 Program 콘텐츠를 다음 C# 코드로 바꿉니다.

using App.TimerHostedService;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<TimerService>();

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

서비스는 AddHostedService 확장 메서드를 사용하여 (Program.cs)에 등록됩니다. 이는 IHostedService 인터페이스를 구현하는 BackgroundService 하위 클래스를 등록할 때 사용하는 것과 동일한 확장 메서드입니다.

서비스 등록에 대한 자세한 내용은 .NET에서 종속성 주입을 참조하세요.

서비스 기능 확인

Visual Studio에서 애플리케이션을 실행하려면 F5를 선택하거나 디버그>디버깅 시작 메뉴 옵션을 선택합니다. .NET CLI를 사용하는 경우 작업 디렉터리에서 dotnet run 명령을 실행합니다.

dotnet run

.NET CLI 실행 명령에 대한 자세한 내용은 dotnet 실행을 참조하세요.

애플리케이션을 실행하여 여러 실행 횟수 증가를 생성할 수 있습니다. 다음과 유사한 출력이 표시됩니다.

info: App.TimerHostedService.TimerService[0]
      TimerHostedService is running.
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: .\timer-service
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 1
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 2
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 3
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 4
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is stopping.

Visual Studio 내에서 애플리케이션을 실행하는 경우 디버그>디버깅 중지...를 선택합니다. 또는 콘솔 창에서 Ctrl + C를 선택하여 취소 신호를 보냅니다.

참고 항목

고려해야 할 여러가지 관련 자습서가 있습니다.