Hospedar ASP.NET Core SignalR em serviços em segundo plano
Por Dave Pringle e Brady Gaster
Este artigo fornece diretrizes para:
- Hospedar Hubs do SignalR usando um processo de trabalho em segundo plano hospedado com o ASP.NET Core.
- Enviar mensagens para clientes conectados de dentro de um BackgroundService do .NET Core.
Exibir ou baixar código de exemplo (como baixar)
Habilitar o SignalR na inicialização do aplicativo
A hospedagem de Hubs do ASP.NET Core SignalR no contexto de um processo de trabalho em segundo plano é idêntica à hospedagem de um Hub em um aplicativo Web do ASP.NET Core. No Program.cs
, chamar builder.Services.AddSignalR
adiciona os serviços necessários à camada da DI (injeção de dependência) do ASP.NET Core para dar suporte ao SignalR. O método MapHub
é chamado no WebApplication
app
para conectar os pontos de extremidade do Hub no pipeline de solicitação do ASP.NET Core.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSignalR();
builder.Services.AddHostedService<Worker>();
var app = builder.Build();
app.MapHub<ClockHub>("/hubs/clock");
app.Run();
No exemplo anterior, a classe ClockHub
implementa a classe Hub<T>
para criar um Hub fortemente tipado. O ClockHub
foi configurado no Program.cs
para responder a solicitações no ponto de extremidade /hubs/clock
.
Para obter mais informações sobre Hubs fortemente tipados, confira o tópico Usar hubs no SignalR para ASP.NET Core.
Observação
Essa funcionalidade não se limita à classe Hub<T>. Qualquer classe que herda do Hub, como oDynamicHub, funciona.
public class ClockHub : Hub<IClock>
{
public async Task SendTimeToClients(DateTime dateTime)
{
await Clients.All.ShowTime(dateTime);
}
}
A interface usada pelo ClockHub
fortemente tipado é a interface IClock
.
public interface IClock
{
Task ShowTime(DateTime currentTime);
}
Chamar um Hub do SignalR a partir de um serviço em segundo plano
Durante a inicialização, a classe Worker
, uma BackgroundService
, é habilitada usando AddHostedService
.
builder.Services.AddHostedService<Worker>();
Como o SignalR também está habilitado durante a fase de inicialização, na qual cada Hub é anexado a um ponto de extremidade individual no pipeline de solicitação HTTP do ASP.NET Core, cada Hub é representado por um IHubContext<T>
no servidor. Usando os recursos de DI do ASP.NET Core, outras classes instanciadas pela camada de hospedagem, como classes BackgroundService
, classes de Controlador MVC ou modelos de página do Razor, podem obter referências a Hubs do lado do servidor aceitando instâncias de IHubContext<ClockHub, IClock>
durante a construção.
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);
}
}
}
Como o método ExecuteAsync
é chamado iterativamente no serviço em segundo plano, a data e a hora atuais do servidor são enviadas aos clientes conectados usando o ClockHub
.
Reagir a eventos SignalR com serviços em segundo plano
Como um aplicativo de página única usando o cliente JavaScript para SignalR, ou um aplicativo da área de trabalho .NET usando o cliente .NET do ASP.NET CoreSignalR, uma implementação BackgroundService
ou IHostedService
também pode ser usada para se conectar a Hubs do SignalR e responder a eventos.
A classe ClockHubClient
implementa a interface IClock
e a interface IHostedService
. Dessa forma, ela pode ser habilitada durante a inicialização para ser executada continuamente e responder a eventos de Hub do servidor.
public partial class ClockHubClient : IClock, IHostedService
{
}
Durante a inicialização, o ClockHubClient
cria uma instância de um HubConnection
e habilita o método IClock.ShowTime
como o manipulador para o evento do Hub 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;
}
Na implementação IHostedService.StartAsync
, o HubConnection
é iniciado de forma assíncrona.
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);
}
}
}
Durante o método IHostedService.StopAsync
, o HubConnection
é descartado de forma assíncrona.
public async Task StopAsync(CancellationToken cancellationToken)
{
await _connection.DisposeAsync();
}
Exibir ou baixar código de exemplo (como baixar)
Habilitar o SignalR na inicialização
A hospedagem de Hubs do ASP.NET Core SignalR no contexto de um processo de trabalho em segundo plano é idêntica à hospedagem de um Hub em um aplicativo Web do ASP.NET Core. No método Startup.ConfigureServices
, chamar services.AddSignalR
adiciona os serviços necessários à camada da DI (injeção de dependência) do ASP.NET Core para dar suporte ao SignalR. Na Startup.Configure
, o método MapHub
é chamado no retorno de chamada UseEndpoints
para conectar os pontos de extremidade do Hub no pipeline de solicitação do 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");
});
}
}
No exemplo anterior, a classe ClockHub
implementa a classe Hub<T>
para criar um Hub fortemente tipado. O ClockHub
foi configurado na classe Startup
para responder a solicitações no ponto de extremidade /hubs/clock
.
Para obter mais informações sobre Hubs fortemente tipados, confira o tópico Usar hubs no SignalR para ASP.NET Core.
Observação
Essa funcionalidade não se limita à classe Hub<T>. Qualquer classe que herda do Hub, como oDynamicHub, funciona.
public class ClockHub : Hub<IClock>
{
public async Task SendTimeToClients(DateTime dateTime)
{
await Clients.All.ShowTime(dateTime);
}
}
A interface usada pelo ClockHub
fortemente tipado é a interface IClock
.
public interface IClock
{
Task ShowTime(DateTime currentTime);
}
Chamar um Hub do SignalR a partir de um serviço em segundo plano
Durante a inicialização, a classe Worker
, uma BackgroundService
, é habilitada usando AddHostedService
.
services.AddHostedService<Worker>();
Como o SignalR também está habilitado durante a fase de Startup
, na qual cada Hub é anexado a um ponto de extremidade individual no pipeline de solicitação HTTP do ASP.NET Core, cada Hub é representado por um IHubContext<T>
no servidor. Usando os recursos de DI do ASP.NET Core, outras classes instanciadas pela camada de hospedagem, como classes BackgroundService
, classes de Controlador MVC ou modelos de página do Razor, podem obter referências a Hubs do lado do servidor aceitando instâncias de IHubContext<ClockHub, IClock>
durante a construção.
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);
}
}
}
Como o método ExecuteAsync
é chamado iterativamente no serviço em segundo plano, a data e a hora atuais do servidor são enviadas aos clientes conectados usando o ClockHub
.
Reagir a eventos SignalR com serviços em segundo plano
Como um aplicativo de página única usando o cliente JavaScript para SignalR, ou um aplicativo da área de trabalho .NET usando o cliente .NET do ASP.NET CoreSignalR, uma implementação BackgroundService
ou IHostedService
também pode ser usada para se conectar a Hubs do SignalR e responder a eventos.
A classe ClockHubClient
implementa a interface IClock
e a interface IHostedService
. Dessa forma, ela pode ser habilitada durante a Startup
para ser executada continuamente e responder a eventos de Hub do servidor.
public partial class ClockHubClient : IClock, IHostedService
{
}
Durante a inicialização, o ClockHubClient
cria uma instância de um HubConnection
e habilita o método IClock.ShowTime
como o manipulador para o evento do Hub 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;
}
Na implementação IHostedService.StartAsync
, o HubConnection
é iniciado de forma assíncrona.
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);
}
}
}
Durante o método IHostedService.StopAsync
, o HubConnection
é descartado de forma assíncrona.
public Task StopAsync(CancellationToken cancellationToken)
{
return _connection.DisposeAsync();
}
Exibir ou baixar código de exemplo (como baixar)
Habilitar o SignalR na inicialização
A hospedagem de Hubs do ASP.NET Core SignalR no contexto de um processo de trabalho em segundo plano é idêntica à hospedagem de um Hub em um aplicativo Web do ASP.NET Core. No método Startup.ConfigureServices
, chamar services.AddSignalR
adiciona os serviços necessários à camada da DI (injeção de dependência) do ASP.NET Core para dar suporte ao SignalR. No Startup.Configure
, o método UseSignalR
é chamado para conectar os pontos de extremidade do Hub no pipeline de solicitação 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");
});
}
}
No exemplo anterior, a classe ClockHub
implementa a classe Hub<T>
para criar um Hub fortemente tipado. O ClockHub
foi configurado na classe Startup
para responder a solicitações no ponto de extremidade /hubs/clock
.
Para obter mais informações sobre Hubs fortemente tipados, confira o tópico Usar hubs no SignalR para ASP.NET Core.
Observação
Essa funcionalidade não se limita à classe Hub<T>. Qualquer classe que herda do Hub, como oDynamicHub, funciona.
public class ClockHub : Hub<IClock>
{
public async Task SendTimeToClients(DateTime dateTime)
{
await Clients.All.ShowTime(dateTime);
}
}
A interface usada pelo ClockHub
fortemente tipado é a interface IClock
.
public interface IClock
{
Task ShowTime(DateTime currentTime);
}
Chamar um Hub do SignalR a partir de um serviço em segundo plano
Durante a inicialização, a classe Worker
, uma BackgroundService
, é habilitada usando AddHostedService
.
services.AddHostedService<Worker>();
Como o SignalR também está habilitado durante a fase de Startup
, na qual cada Hub é anexado a um ponto de extremidade individual no pipeline de solicitação HTTP do ASP.NET Core, cada Hub é representado por um IHubContext<T>
no servidor. Usando os recursos de DI do ASP.NET Core, outras classes instanciadas pela camada de hospedagem, como classes BackgroundService
, classes de Controlador MVC ou modelos de página do Razor, podem obter referências a Hubs do lado do servidor aceitando instâncias de IHubContext<ClockHub, IClock>
durante a construção.
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);
}
}
}
Como o método ExecuteAsync
é chamado iterativamente no serviço em segundo plano, a data e a hora atuais do servidor são enviadas aos clientes conectados usando o ClockHub
.
Reagir a eventos SignalR com serviços em segundo plano
Como um aplicativo de página única usando o cliente JavaScript para SignalR, ou um aplicativo da área de trabalho .NET usando o cliente .NET do ASP.NET CoreSignalR, uma implementação BackgroundService
ou IHostedService
também pode ser usada para se conectar a Hubs do SignalR e responder a eventos.
A classe ClockHubClient
implementa a interface IClock
e a interface IHostedService
. Dessa forma, ela pode ser habilitada durante a Startup
para ser executada continuamente e responder a eventos de Hub do servidor.
public partial class ClockHubClient : IClock, IHostedService
{
}
Durante a inicialização, o ClockHubClient
cria uma instância de um HubConnection
e habilita o método IClock.ShowTime
como o manipulador para o evento do Hub 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;
}
Na implementação IHostedService.StartAsync
, o HubConnection
é iniciado de forma assíncrona.
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);
}
}
}
Durante o método IHostedService.StopAsync
, o HubConnection
é descartado de forma assíncrona.
public Task StopAsync(CancellationToken cancellationToken)
{
return _connection.DisposeAsync();
}