logo MSJO.kr

Worker Services in .NET Core 3.0

2019-09-12
MsJ
   

닷넷 코어 3.0 버전에는 Worker Service라 불리는 새로운 template이 추가되었다. 윈도우 서비스 프로그램을 쉽게 작성하게 해준다. 아래의 예제는 닷넷 유튜브 강좌로 유명한 IAmTimCorey가 강의한 내용을 소스 코드 형식으로 정리한 것이다.

사용한 환경은 Visual Studio 2019 16.2.5, .NET Core 3.0 Preview 7이며 프로젝트 생성 시 ASP.NET Core 웹 응용 프로그램으로 프로젝트를 진행 후 작업자 서비스(Worker Service)를 선택한다.

패키지 추가 설치
  • Serilog.AspNetCore
  • Serilog.Sinks.File
  • Microsoft.Extensions.Hosting.WindowsServices

최종 작성된 실행 파일을 로그 텍스트 파일과 같은 위치에 놓고 윈도우 서비스를 다음과 같이 등록한다. 파워셸 관리자 모드 필요.

PS C:\> sc.exe create WebsiteStatus binpath=C:\Test\WebsiteStatus.exe start=auto
[SC] CreateService 성공
PS C:\> sc.exe delete WebsiteStatus
[SC] DeleteService 성공

아래는 전체 소스이다. Program.cs, Worker.cs

프로그램 소스
// Worker.cs
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace WebsiteStatus
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        private HttpClient client;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        public override Task StartAsync(CancellationToken cancellationToken)
        {
            client = new HttpClient();
            return base.StartAsync(cancellationToken);
        }

        public override Task StopAsync(CancellationToken cancellationToken)
        {
            client.Dispose();
            return base.StopAsync(cancellationToken);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                var result = await client.GetAsync("https://localhost", stoppingToken);
                if (result.IsSuccessStatusCode)
                {
                    _logger.LogInformation("The website is up. Status code {StatusCode}", result.StatusCode);
                }
                else
                {
                    _logger.LogError("The website is down. Status code {StatusCode}", result.StatusCode);
                }

                await Task.Delay(5000, stoppingToken);
            }
        }
    }
}
// Program.cs
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using System;

namespace WebsiteStatus
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                .Enrich.FromLogContext()
                .WriteTo.File(@"C:\Test\LogFile.txt").CreateLogger();

            try
            {
                Log.Information("Starting up the service");
                CreateHostBuilder(args).Build().Run();
            }
            catch (Exception e)
            {
                Log.Fatal(e, "There was a problem starting the service");
            }
            finally
            {
                Log.CloseAndFlush();
            }

            
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseWindowsService()
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();
                }).UseSerilog();
    }
}
Reference

Prεv(Θld)   Nεxt(Nεw)
Content
Search     RSS Feed     BY-NC-ND