在后台服务中托管 ASP.NET Core SignalR
作者:Dave Pringle 和 Brady Gaster
本文提供以下指导:
- 使用通过 ASP.NET Core 托管的后台工作进程托管 SignalR 中心。
- 从 NET Core BackgroundService 中将消息发送到连接的客户端。
在应用启动时启用 SignalR
在后台工作进程上下文中托管 ASP.NET Core SignalR 中心与在 ASP.NET Core Web 应用中托管中心完全相同。 在 Program.cs
中,调用 builder.Services.AddSignalR
会将所需的服务添加到 ASP.NET Core 依赖关系注入 (DI) 层来支持 SignalR。 对 WebApplication
app
调用 MapHub
方法以连接 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();
在前面的示例中,ClockHub
类实现 Hub<T>
类以创建强类型的中心。 ClockHub
已在 Program.cs
中配置为响应终结点 /hubs/clock
处的请求。
有关强类型中心的详细信息,请参阅在 SignalR for ASP.NET Core 中使用中心。
注意
此功能并不限于中心<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 中心
在启动过程中,将使用 AddHostedService
启用 Worker
类 BackgroundService
。
builder.Services.AddHostedService<Worker>();
由于 SignalR 也会在启动期间启用,其中每个中心会附加到 ASP.NET Core 的 HTTP 请求管道中的各个终结点,因此,每个中心在服务器上由 IHubContext<T>
表示。 通过使用 ASP.NET Core 的 DI 功能,由托管层实例化的其他类(例如 BackgroundService
类、MVC 控制器类或 Razor 页面模型)可以在构造期间接受 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客户端的 .NET 桌面应用一样,BackgroundService
或 IHostedService
实现也可用于连接到 SignalR 中心并对事件进行响应。
ClockHubClient
类同时实现 IClock
接口和 IHostedService
接口。 这样,就可在启动期间启用它以持续运行并对来自服务器的中心事件进行响应。
public partial class ClockHubClient : IClock, IHostedService
{
}
在初始化期间,ClockHubClient
创建 HubConnection
的实例,并启用 IClock.ShowTime
方法作为中心的 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();
}
在 startup 中启用 SignalR
在后台工作进程上下文中托管 ASP.NET Core SignalR 中心与在 ASP.NET Core Web 应用中托管中心完全相同。 在 Startup.ConfigureServices
方法中,调用 services.AddSignalR
会将所需的服务添加到 ASP.NET Core Dependency Injection (DI) 层以支持 SignalR。 在 Startup.Configure
中,会在 UseEndpoints
回叫中调用 MapHub
方法来连接 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>
类以创建强类型的中心。 ClockHub
已在 Startup
中配置为响应终结点 /hubs/clock
处的请求。
有关强类型中心的详细信息,请参阅在 SignalR for ASP.NET Core 中使用中心。
注意
此功能并不限于中心<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 中心
在启动过程中,将使用 AddHostedService
启用 Worker
类 BackgroundService
。
services.AddHostedService<Worker>();
由于 SignalR 也会在 Startup
期间启用,其中每个中心会附加到 ASP.NET Core 的 HTTP 请求管道中的各个终结点,因此,每个中心在服务器上由 IHubContext<T>
表示。 通过使用 ASP.NET Core 的 DI 功能,由托管层实例化的其他类(例如 BackgroundService
类、MVC 控制器类或 Razor 页面模型)可以在构造期间接受 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客户端的 .NET 桌面应用一样,BackgroundService
或 IHostedService
实现也可用于连接到 SignalR 中心并对事件进行响应。
ClockHubClient
类同时实现 IClock
接口和 IHostedService
接口。 这样一来,可以在 Startup
期间启用它以持续运行并对来自服务器的中心事件进行响应。
public partial class ClockHubClient : IClock, IHostedService
{
}
在初始化期间,ClockHubClient
创建 HubConnection
的实例,并启用 IClock.ShowTime
方法作为中心的 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();
}
在 startup 中启用 SignalR
在后台工作进程上下文中托管 ASP.NET Core SignalR 中心与在 ASP.NET Core Web 应用中托管中心完全相同。 在 Startup.ConfigureServices
方法中,调用 services.AddSignalR
会将所需的服务添加到 ASP.NET Core Dependency Injection (DI) 层以支持 SignalR。 在 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>
类以创建强类型的中心。 ClockHub
已在 Startup
中配置为响应终结点 /hubs/clock
处的请求。
有关强类型中心的详细信息,请参阅在 SignalR for ASP.NET Core 中使用中心。
注意
此功能并不限于中心<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 中心
在启动过程中,将使用 AddHostedService
启用 Worker
类 BackgroundService
。
services.AddHostedService<Worker>();
由于 SignalR 也会在 Startup
期间启用,其中每个中心会附加到 ASP.NET Core 的 HTTP 请求管道中的各个终结点,因此,每个中心在服务器上由 IHubContext<T>
表示。 通过使用 ASP.NET Core 的 DI 功能,由托管层实例化的其他类(例如 BackgroundService
类、MVC 控制器类或 Razor 页面模型)可以在构造期间接受 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客户端的 .NET 桌面应用一样,BackgroundService
或 IHostedService
实现也可用于连接到 SignalR 中心并对事件进行响应。
ClockHubClient
类同时实现 IClock
接口和 IHostedService
接口。 这样一来,可以在 Startup
期间启用它以持续运行并对来自服务器的中心事件进行响应。
public partial class ClockHubClient : IClock, IHostedService
{
}
在初始化期间,ClockHubClient
创建 HubConnection
的实例,并启用 IClock.ShowTime
方法作为中心的 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();
}