백그라운드 서비스에서 ASP.NET Core SignalR 호스트

작성자: Dave Pringle, Brady Gaster

이 문서에서는 다음을 위한 지침을 제공합니다.

  • ASP.NET Core를 호스팅한 백그라운드 작업자 프로세스를 사용하는 SignalR 허브 호스팅.
  • .NET Core BackgroundService 내에서 연결된 클라이언트로 메시지 보내기.

샘플 코드 보기 및 다운로드(다운로드 방법)

앱 시작 시 SignalR 사용

백그라운드 작업자 프로세스의 컨텍스트에서 ASP.NET Core SignalR 허브를 호스팅하는 것은 ASP.NET Core 웹앱에서 허브를 호스팅하는 것과 동일합니다. Program.cs에서 builder.Services.AddSignalR을 호출하면 SignalR을 지원하기 위해 필수 서비스가 ASP.NET Core DI(종속성 주입) 계층에 추가됩니다. 메서드는 MapHub ASP.NET Core 요청 파이프라인의 허브 엔드포인트를 연결하기 위해 호출 WebApplication app 됩니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSignalR();
builder.Services.AddHostedService<Worker>();

var app = builder.Build();

app.MapHub<ClockHub>("/hubs/clock");

app.Run();

앞의 예제에서 ClockHub 클래스는 Hub<T> 클래스를 구현하여 강력한 형식의 허브를 만듭니다. ClockHub는 엔드포인트 /hubs/clock에서 요청에 응답하도록 Program.cs에 구성되었습니다.

강력한 형식의 허브에 대한 자세한 내용은 ASP.NET Core를 위한 SignalR에서 허브 사용을 참조하세요.

참고 항목

이 기능은 Hub<T> 클래스로 제한되지 않습니다. DynamicHub와 같이 허브에서 상속되는 모든 클래스가 작동합니다.

public class ClockHub : Hub<IClock>
{
    public async Task SendTimeToClients(DateTime dateTime)
    {
        await Clients.All.ShowTime(dateTime);
    }
}

강력한 형식의 ClockHub에서 사용하는 인터페이스는 IClock 인터페이스입니다.

public interface IClock
{
    Task ShowTime(DateTime currentTime);
}

백그라운드 서비스에서 SignalR 허브 호출

시작하는 동안 Worker 클래스인 BackgroundServiceAddHostedService를 사용하여 사용하도록 설정됩니다.

builder.Services.AddHostedService<Worker>();

또한 SignalR은 시작 단계 중에 활성화되며 시작 단계에서 각 허브가 ASP.NET Core의 HTTP 요청 파이프라인의 개별 엔드포인트에 연결되므로 각 허브는 서버에서 IHubContext<T>로 표시됩니다. ASP.NET Core의 DI 기능을 사용하면 BackgroundService 클래스, MVC 컨트롤러 클래스 또는 Razor Page 모델과 같이 호스팅 계층에서 인스턴스화된 다른 클래스는 구성 중에 IHubContext<ClockHub, IClock>의 인스턴스를 수락하여 서버 쪽 허브에 대한 참조를 얻을 수 있습니다.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IHubContext<ClockHub, IClock> _clockHub;

    public Worker(ILogger<Worker> logger, IHubContext<ClockHub, IClock> clockHub)
    {
        _logger = logger;
        _clockHub = clockHub;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {Time}", DateTime.Now);
            await _clockHub.Clients.All.ShowTime(DateTime.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

ExecuteAsync 메서드가 백그라운드 서비스에서 반복적으로 호출되면 서버의 현재 날짜와 시간이 ClockHub를 사용하여 연결된 클라이언트로 전송됩니다.

백그라운드 서비스로 SignalR 이벤트에 대응

SignalR용 JavaScript 클라이언트를 사용하는 단일 페이지 앱 또는 ASP.NET Core SignalR .NET Client를 사용하는 .NET 데스크톱 앱과 마찬가지로 BackgroundService 또는 IHostedService 구현을 사용하여 SignalR 허브에 연결하고 이벤트에 응답할 수도 있습니다.

ClockHubClient 클래스는 IClock 인터페이스와 IHostedService 인터페이스를 모두 구현합니다. 이러한 방식으로 지속적으로 실행하고 서버의 허브 이벤트에 응답하도록 시작 중에 설정할 수 있습니다.

public partial class ClockHubClient : IClock, IHostedService
{
}

초기화하는 동안 ClockHubClientHubConnection의 인스턴스를 만들고, 허브의 ShowTime 이벤트에 대한 처리기로 IClock.ShowTime 메서드를 사용하도록 설정합니다.

private readonly ILogger<ClockHubClient> _logger;
private HubConnection _connection;

public ClockHubClient(ILogger<ClockHubClient> logger)
{
    _logger = logger;
    
    _connection = new HubConnectionBuilder()
        .WithUrl(Strings.HubUrl)
        .Build();

    _connection.On<DateTime>(Strings.Events.TimeSent, ShowTime);
}

public Task ShowTime(DateTime currentTime)
{
    _logger.LogInformation("{CurrentTime}", currentTime.ToShortTimeString());

    return Task.CompletedTask;
}

IHostedService.StartAsync 구현에서 HubConnection은 비동기적으로 시작됩니다.

public async Task StartAsync(CancellationToken cancellationToken)
{
    // Loop is here to wait until the server is running
    while (true)
    {
        try
        {
            await _connection.StartAsync(cancellationToken);

            break;
        }
        catch
        {
            await Task.Delay(1000, cancellationToken);
        }
    }
}

IHostedService.StopAsync 메서드 중에 HubConnection은 비동기적으로 삭제됩니다.

public async Task StopAsync(CancellationToken cancellationToken)
{
    await _connection.DisposeAsync();
}

샘플 코드 보기 및 다운로드(다운로드 방법)

시작 시 SignalR 사용

백그라운드 작업자 프로세스의 컨텍스트에서 ASP.NET Core SignalR 허브를 호스팅하는 것은 ASP.NET Core 웹앱에서 허브를 호스팅하는 것과 동일합니다. Startup.ConfigureServices 메서드에서 services.AddSignalR을 호출하면 SignalR을 지원하기 위해 필수 서비스가 ASP.NET Core DI(종속성 주입) 계층에 추가됩니다. Startup.Configure에서 MapHub 메서드는 UseEndpoints 콜백에서 호출되어 ASP.NET Core 요청 파이프라인의 허브 엔드포인트를 연결합니다.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSignalR();
        services.AddHostedService<Worker>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHub<ClockHub>("/hubs/clock");
        });
    }
}

앞의 예제에서 ClockHub 클래스는 Hub<T> 클래스를 구현하여 강력한 형식의 허브를 만듭니다. ClockHubStartup 클래스에서 엔드포인트 /hubs/clock의 요청에 응답하도록 구성되었습니다.

강력한 형식의 허브에 대한 자세한 내용은 ASP.NET Core를 위한 SignalR에서 허브 사용을 참조하세요.

참고 항목

이 기능은 Hub<T> 클래스로 제한되지 않습니다. DynamicHub와 같이 허브에서 상속되는 모든 클래스가 작동합니다.

public class ClockHub : Hub<IClock>
{
    public async Task SendTimeToClients(DateTime dateTime)
    {
        await Clients.All.ShowTime(dateTime);
    }
}

강력한 형식의 ClockHub에서 사용하는 인터페이스는 IClock 인터페이스입니다.

public interface IClock
{
    Task ShowTime(DateTime currentTime);
}

백그라운드 서비스에서 SignalR 허브 호출

시작하는 동안 Worker 클래스인 BackgroundServiceAddHostedService를 사용하여 사용하도록 설정됩니다.

services.AddHostedService<Worker>();

또한 SignalR은 Startup 단계 중에 활성화되며, 각 허브는 ASP.NET Core의 HTTP 요청 파이프라인에서 개별 엔드포인트에 연결되므로 각 허브는 서버의 IHubContext<T>로 표시됩니다. ASP.NET Core의 DI 기능을 사용하면 BackgroundService 클래스, MVC 컨트롤러 클래스 또는 Razor Page 모델과 같이 호스팅 계층에서 인스턴스화된 다른 클래스는 구성 중에 IHubContext<ClockHub, IClock>의 인스턴스를 수락하여 서버 쪽 허브에 대한 참조를 얻을 수 있습니다.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IHubContext<ClockHub, IClock> _clockHub;

    public Worker(ILogger<Worker> logger, IHubContext<ClockHub, IClock> clockHub)
    {
        _logger = logger;
        _clockHub = clockHub;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {Time}", DateTime.Now);
            await _clockHub.Clients.All.ShowTime(DateTime.Now);
            await Task.Delay(1000);
        }
    }
}

ExecuteAsync 메서드가 백그라운드 서비스에서 반복적으로 호출되면 서버의 현재 날짜와 시간이 ClockHub를 사용하여 연결된 클라이언트로 전송됩니다.

백그라운드 서비스로 SignalR 이벤트에 대응

SignalR용 JavaScript 클라이언트를 사용하는 단일 페이지 앱 또는 ASP.NET Core SignalR .NET Client를 사용하는 .NET 데스크톱 앱과 마찬가지로 BackgroundService 또는 IHostedService 구현을 사용하여 SignalR 허브에 연결하고 이벤트에 응답할 수도 있습니다.

ClockHubClient 클래스는 IClock 인터페이스와 IHostedService 인터페이스를 모두 구현합니다. 이러한 방식으로 Startup 중에 지속적으로 실행하고 서버의 허브 이벤트에 응답하도록 설정할 수 있습니다.

public partial class ClockHubClient : IClock, IHostedService
{
}

초기화하는 동안 ClockHubClientHubConnection의 인스턴스를 만들고, 허브의 ShowTime 이벤트에 대한 처리기로 IClock.ShowTime 메서드를 사용하도록 설정합니다.

private readonly ILogger<ClockHubClient> _logger;
private HubConnection _connection;

public ClockHubClient(ILogger<ClockHubClient> logger)
{
    _logger = logger;
    
    _connection = new HubConnectionBuilder()
        .WithUrl(Strings.HubUrl)
        .Build();

    _connection.On<DateTime>(Strings.Events.TimeSent, ShowTime);
}

public Task ShowTime(DateTime currentTime)
{
    _logger.LogInformation("{CurrentTime}", currentTime.ToShortTimeString());

    return Task.CompletedTask;
}

IHostedService.StartAsync 구현에서 HubConnection은 비동기적으로 시작됩니다.

public async Task StartAsync(CancellationToken cancellationToken)
{
    // Loop is here to wait until the server is running
    while (true)
    {
        try
        {
            await _connection.StartAsync(cancellationToken);

            break;
        }
        catch
        {
            await Task.Delay(1000);
        }
    }
}

IHostedService.StopAsync 메서드 중에 HubConnection은 비동기적으로 삭제됩니다.

public Task StopAsync(CancellationToken cancellationToken)
{
    return _connection.DisposeAsync();
}

샘플 코드 보기 및 다운로드(다운로드 방법)

시작 시 SignalR 사용

백그라운드 작업자 프로세스의 컨텍스트에서 ASP.NET Core SignalR 허브를 호스팅하는 것은 ASP.NET Core 웹앱에서 허브를 호스팅하는 것과 동일합니다. Startup.ConfigureServices 메서드에서 services.AddSignalR을 호출하면 SignalR을 지원하기 위해 필수 서비스가 ASP.NET Core DI(종속성 주입) 계층에 추가됩니다. Startup.Configure에서 UseSignalR 메서드가 호출되어 ASP.NET Core 요청 파이프라인의 허브 엔드포인트를 연결합니다.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSignalR();
        services.AddHostedService<Worker>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseSignalR((routes) =>
        {
            routes.MapHub<ClockHub>("/hubs/clock");
        });
    }
}

앞의 예제에서 ClockHub 클래스는 Hub<T> 클래스를 구현하여 강력한 형식의 허브를 만듭니다. ClockHubStartup 클래스에서 엔드포인트 /hubs/clock의 요청에 응답하도록 구성되었습니다.

강력한 형식의 허브에 대한 자세한 내용은 ASP.NET Core를 위한 SignalR에서 허브 사용을 참조하세요.

참고 항목

이 기능은 Hub<T> 클래스로 제한되지 않습니다. DynamicHub와 같이 허브에서 상속되는 모든 클래스가 작동합니다.

public class ClockHub : Hub<IClock>
{
    public async Task SendTimeToClients(DateTime dateTime)
    {
        await Clients.All.ShowTime(dateTime);
    }
}

강력한 형식의 ClockHub에서 사용하는 인터페이스는 IClock 인터페이스입니다.

public interface IClock
{
    Task ShowTime(DateTime currentTime);
}

백그라운드 서비스에서 SignalR 허브 호출

시작하는 동안 Worker 클래스인 BackgroundServiceAddHostedService를 사용하여 사용하도록 설정됩니다.

services.AddHostedService<Worker>();

또한 SignalR은 Startup 단계 중에 활성화되며, 각 허브는 ASP.NET Core의 HTTP 요청 파이프라인에서 개별 엔드포인트에 연결되므로 각 허브는 서버의 IHubContext<T>로 표시됩니다. ASP.NET Core의 DI 기능을 사용하면 BackgroundService 클래스, MVC 컨트롤러 클래스 또는 Razor Page 모델과 같이 호스팅 계층에서 인스턴스화된 다른 클래스는 구성 중에 IHubContext<ClockHub, IClock>의 인스턴스를 수락하여 서버 쪽 허브에 대한 참조를 얻을 수 있습니다.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IHubContext<ClockHub, IClock> _clockHub;

    public Worker(ILogger<Worker> logger, IHubContext<ClockHub, IClock> clockHub)
    {
        _logger = logger;
        _clockHub = clockHub;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {Time}", DateTime.Now);
            await _clockHub.Clients.All.ShowTime(DateTime.Now);
            await Task.Delay(1000);
        }
    }
}

ExecuteAsync 메서드가 백그라운드 서비스에서 반복적으로 호출되면 서버의 현재 날짜와 시간이 ClockHub를 사용하여 연결된 클라이언트로 전송됩니다.

백그라운드 서비스로 SignalR 이벤트에 대응

SignalR용 JavaScript 클라이언트를 사용하는 단일 페이지 앱 또는 ASP.NET Core SignalR .NET Client를 사용하는 .NET 데스크톱 앱과 마찬가지로 BackgroundService 또는 IHostedService 구현을 사용하여 SignalR 허브에 연결하고 이벤트에 응답할 수도 있습니다.

ClockHubClient 클래스는 IClock 인터페이스와 IHostedService 인터페이스를 모두 구현합니다. 이러한 방식으로 Startup 중에 지속적으로 실행하고 서버의 허브 이벤트에 응답하도록 설정할 수 있습니다.

public partial class ClockHubClient : IClock, IHostedService
{
}

초기화하는 동안 ClockHubClientHubConnection의 인스턴스를 만들고, 허브의 ShowTime 이벤트에 대한 처리기로 IClock.ShowTime 메서드를 사용하도록 설정합니다.

private readonly ILogger<ClockHubClient> _logger;
private HubConnection _connection;

public ClockHubClient(ILogger<ClockHubClient> logger)
{
    _logger = logger;
    
    _connection = new HubConnectionBuilder()
        .WithUrl(Strings.HubUrl)
        .Build();

    _connection.On<DateTime>(Strings.Events.TimeSent, 
        dateTime => _ = ShowTime(dateTime));
}

public Task ShowTime(DateTime currentTime)
{
    _logger.LogInformation("{CurrentTime}", currentTime.ToShortTimeString());

    return Task.CompletedTask;
}

IHostedService.StartAsync 구현에서 HubConnection은 비동기적으로 시작됩니다.

public async Task StartAsync(CancellationToken cancellationToken)
{
    // Loop is here to wait until the server is running
    while (true)
    {
        try
        {
            await _connection.StartAsync(cancellationToken);

            break;
        }
        catch
        {
            await Task.Delay(1000);
        }
    }
}

IHostedService.StopAsync 메서드 중에 HubConnection은 비동기적으로 삭제됩니다.

public Task StopAsync(CancellationToken cancellationToken)
{
    return _connection.DisposeAsync();
}

추가 리소스