Hospedar SignalR de ASP.NET Core en servicios en segundo plano
Por Dave Pringle y Brady Gaster
En este artículo se proporcionan instrucciones para:
- Hospedaje de concentradores de SignalR mediante un proceso de trabajo en segundo plano hospedado con ASP.NET Core.
- Envío de mensajes a clientes conectados desde un backgroundService de .NET Core.
Vea o descargue el código de ejemplo (cómo descargarlo)
Habilitar SignalR al iniciar la aplicación
Hospedar concentradores de SignalR de ASP.NET Core en el contexto de un proceso de trabajo en segundo plano es idéntico al hospedaje de un concentrador en una aplicación web de ASP.NET Core. En Program.cs
, al llamar a builder.Services.AddSignalR
se agregan los servicios necesarios a la capa de inserción de dependencias (DI) ASP.NET Core para admitir SignalR. Se llama al método MapHub
en WebApplication
app
para conectar los puntos de conexión del Centro en la canalización de la solicitud de 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();
En el ejemplo anterior, la clase de ClockHub
implementa la clase de Hub<T>
para crear un concentrador fuertemente tipado. ClockHub
se ha configurado en Program.cs
para responder a las solicitudes en el punto de conexión /hubs/clock
.
Para obtener más información sobre los concentradores fuertemente tipados, consulte Usar concentradores en SignalR para ASP.NET Core.
Nota
Esta funcionalidad no se limita a la clase de concentrador<T>. Cualquier clase que herede del concentrador, como DynamicHub, funciona.
public class ClockHub : Hub<IClock>
{
public async Task SendTimeToClients(DateTime dateTime)
{
await Clients.All.ShowTime(dateTime);
}
}
La interfaz utilizada por el fuertemente tipado ClockHub
es la interfaz de IClock
.
public interface IClock
{
Task ShowTime(DateTime currentTime);
}
Llamar a un concentrador de SignalR desde un servicio en segundo plano
Durante el inicio, la clase de Worker
, un BackgroundService
, se habilita mediante AddHostedService
.
builder.Services.AddHostedService<Worker>();
Puesto que SignalR también se habilita durante la fase de inicio, en la que cada concentrador está asociado a un punto de conexión individual en la canalización de solicitudes HTTP de ASP.NET Core, cada concentrador se representa mediante un IHubContext<T>
en el servidor. Con las características de inserción de dependencias de ASP.NET Core, otras clases de las que crea una instancia la capa de hospedaje, como las clases de BackgroundService
, las clases de controlador de MVC o modelos de página de Razor, pueden obtener referencias a concentradores del lado servidor aceptando instancias de IHubContext<ClockHub, IClock>
durante la construcción.
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 el método ExecuteAsync
se denomina iterativamente en el servicio en segundo plano, la fecha y hora actuales del servidor se envían a los clientes conectados mediante ClockHub
.
Responder a eventos de SignalR con servicios en segundo plano
Al igual que una aplicación de página única mediante el cliente de JavaScript para SignalR, o una aplicación de escritorio de .NET mediante el cliente .NET SignalR de ASP.NET Core, también se puede usar una implementación BackgroundService
o IHostedService
para conectarse a concentradores de SignalR y responder a eventos.
La clase de ClockHubClient
implementa la interfaz de IClock
y la interfaz de IHostedService
. De este modo, se puede habilitar durante el inicio para que se ejecute continuamente y responder a eventos del concentrador desde el servidor.
public partial class ClockHubClient : IClock, IHostedService
{
}
Durante la inicialización, ClockHubClient
crea una instancia de HubConnection
y habilita el método IClock.ShowTime
como controlador para el evento de ShowTime
del concentrador.
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;
}
En la implementación de IHostedService.StartAsync
, HubConnection
se inicia de forma asincrónica.
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 el método IHostedService.StopAsync
, HubConnection
se elimina de forma asincrónica.
public async Task StopAsync(CancellationToken cancellationToken)
{
await _connection.DisposeAsync();
}
Vea o descargue el código de ejemplo (cómo descargarlo)
Habilitar SignalR en el inicio
Hospedar concentradores de SignalR de ASP.NET Core en el contexto de un proceso de trabajo en segundo plano es idéntico al hospedaje de un concentrador en una aplicación web de ASP.NET Core. En el método Startup.ConfigureServices
, al llamar a services.AddSignalR
se agregan los servicios necesarios a la capa de inserción de dependencias (DI) ASP.NET Core para admitir SignalR. En Startup.Configure
, se llama al método MapHub
en la devolución de llamada de UseEndpoints
para conectar los puntos de conexión del concentrador en la canalización de solicitud de 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");
});
}
}
En el ejemplo anterior, la clase de ClockHub
implementa la clase de Hub<T>
para crear un concentrador fuertemente tipado. ClockHub
se ha configurado en la clase de Startup
para responder a las solicitudes en el punto de conexión /hubs/clock
.
Para obtener más información sobre los concentradores fuertemente tipados, consulte Usar concentradores en SignalR para ASP.NET Core.
Nota
Esta funcionalidad no se limita a la clase de concentrador<T>. Cualquier clase que herede del concentrador, como DynamicHub, funciona.
public class ClockHub : Hub<IClock>
{
public async Task SendTimeToClients(DateTime dateTime)
{
await Clients.All.ShowTime(dateTime);
}
}
La interfaz utilizada por el fuertemente tipado ClockHub
es la interfaz de IClock
.
public interface IClock
{
Task ShowTime(DateTime currentTime);
}
Llamar a un concentrador de SignalR desde un servicio en segundo plano
Durante el inicio, la clase de Worker
, un BackgroundService
, se habilita mediante AddHostedService
.
services.AddHostedService<Worker>();
Puesto que SignalR también se habilita durante la fase de Startup
, en la que cada concentrador está asociado a un punto de conexión individual en la canalización de solicitudes HTTP de ASP.NET Core, cada concentrador se representa mediante un IHubContext<T>
en el servidor. Con las características de inserción de dependencias de ASP.NET Core, otras clases de las que crea una instancia la capa de hospedaje, como las clases de BackgroundService
, las clases de controlador de MVC o modelos de página de Razor, pueden obtener referencias a concentradores del lado servidor aceptando instancias de IHubContext<ClockHub, IClock>
durante la construcción.
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 el método ExecuteAsync
se denomina iterativamente en el servicio en segundo plano, la fecha y hora actuales del servidor se envían a los clientes conectados mediante ClockHub
.
Responder a eventos de SignalR con servicios en segundo plano
Al igual que una aplicación de página única mediante el cliente de JavaScript para SignalR, o una aplicación de escritorio de .NET mediante el cliente .NET SignalR de ASP.NET Core, también se puede usar una implementación BackgroundService
o IHostedService
para conectarse a concentradores de SignalR y responder a eventos.
La clase de ClockHubClient
implementa la interfaz de IClock
y la interfaz de IHostedService
. De este modo, se puede habilitar durante el Startup
para que se ejecute continuamente y responder a eventos del concentrador desde el servidor.
public partial class ClockHubClient : IClock, IHostedService
{
}
Durante la inicialización, ClockHubClient
crea una instancia de HubConnection
y habilita el método IClock.ShowTime
como controlador para el evento de ShowTime
del concentrador.
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;
}
En la implementación de IHostedService.StartAsync
, HubConnection
se inicia de forma asincrónica.
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 el método IHostedService.StopAsync
, HubConnection
se elimina de forma asincrónica.
public Task StopAsync(CancellationToken cancellationToken)
{
return _connection.DisposeAsync();
}
Vea o descargue el código de ejemplo (cómo descargarlo)
Habilitar SignalR en el inicio
Hospedar concentradores de SignalR de ASP.NET Core en el contexto de un proceso de trabajo en segundo plano es idéntico al hospedaje de un concentrador en una aplicación web de ASP.NET Core. En el método Startup.ConfigureServices
, al llamar a services.AddSignalR
se agregan los servicios necesarios a la capa de inserción de dependencias (DI) ASP.NET Core para admitir SignalR. En Startup.Configure
, se llama al método UseSignalR
para conectar el(los) punto(s) de conexión del concentrador en la canalización de solicitud de 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");
});
}
}
En el ejemplo anterior, la clase de ClockHub
implementa la clase de Hub<T>
para crear un concentrador fuertemente tipado. ClockHub
se ha configurado en la clase de Startup
para responder a las solicitudes en el punto de conexión /hubs/clock
.
Para obtener más información sobre los concentradores fuertemente tipados, consulte Usar concentradores en SignalR para ASP.NET Core.
Nota
Esta funcionalidad no se limita a la clase de concentrador<T>. Cualquier clase que herede del concentrador, como DynamicHub, funciona.
public class ClockHub : Hub<IClock>
{
public async Task SendTimeToClients(DateTime dateTime)
{
await Clients.All.ShowTime(dateTime);
}
}
La interfaz utilizada por el fuertemente tipado ClockHub
es la interfaz de IClock
.
public interface IClock
{
Task ShowTime(DateTime currentTime);
}
Llamar a un concentrador de SignalR desde un servicio en segundo plano
Durante el inicio, la clase de Worker
, un BackgroundService
, se habilita mediante AddHostedService
.
services.AddHostedService<Worker>();
Puesto que SignalR también se habilita durante la fase de Startup
, en la que cada concentrador está asociado a un punto de conexión individual en la canalización de solicitudes HTTP de ASP.NET Core, cada concentrador se representa mediante un IHubContext<T>
en el servidor. Con las características de inserción de dependencias de ASP.NET Core, otras clases de las que crea una instancia la capa de hospedaje, como las clases de BackgroundService
, las clases de controlador de MVC o modelos de página de Razor, pueden obtener referencias a concentradores del lado servidor aceptando instancias de IHubContext<ClockHub, IClock>
durante la construcción.
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 el método ExecuteAsync
se denomina iterativamente en el servicio en segundo plano, la fecha y hora actuales del servidor se envían a los clientes conectados mediante ClockHub
.
Responder a eventos de SignalR con servicios en segundo plano
Al igual que una aplicación de página única mediante el cliente de JavaScript para SignalR, o una aplicación de escritorio de .NET mediante el cliente .NET SignalR de ASP.NET Core, también se puede usar una implementación BackgroundService
o IHostedService
para conectarse a concentradores de SignalR y responder a eventos.
La clase de ClockHubClient
implementa la interfaz de IClock
y la interfaz de IHostedService
. De este modo, se puede habilitar durante el Startup
para que se ejecute continuamente y responder a eventos del concentrador desde el servidor.
public partial class ClockHubClient : IClock, IHostedService
{
}
Durante la inicialización, ClockHubClient
crea una instancia de HubConnection
y habilita el método IClock.ShowTime
como controlador para el evento de ShowTime
del concentrador.
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;
}
En la implementación de IHostedService.StartAsync
, HubConnection
se inicia de forma asincrónica.
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 el método IHostedService.StopAsync
, HubConnection
se elimina de forma asincrónica.
public Task StopAsync(CancellationToken cancellationToken)
{
return _connection.DisposeAsync();
}