.net-core - SignalR Core Hub 与 BackgroundService .NET Core 交互
问题描述
我已阅读有关如何通过信号器核心集线器从后台服务向客户端发送通知的文档。如何接收来自客户端的通知到后台服务?
后台服务应该只是一个单例。
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<QueueProcessor>();
services.AddSignalR();
}
public void Configure(IApplicationBuilder app)
{
app.UseSignalR(routes =>
{
routes.MapHub<AutoCommitHub>("/autocommithub");
});
}
}
public class QueueProcessor : BackgroundService
{
private int interval;
public QueueProcessor(IHubContext<AutoCommitHub> hubContext)
{
this.hub = hubContext;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await BeginProcessingOrders();
Thread.Sleep(interval);
}
}
internal async Task BroadcastProcessStarted(string orderNumber)
{
await hub.Clients.All.SendAsync("ReceiveOrderStarted",
orderNumber);
}
internal void SetInterval(int interval)
{
this.interval = interval;
}
}
public class AutoCommitHub : Hub
{
private readonly QueueProcessor queueProcessor;
public AutoCommitHub(QueueProcessor _processor)
{
queueProcessor = _processor;
}
public void SetIntervalSpeed(int interval)
{
queueProcessor.SetInterval(interval);
}
}
我需要能够从客户端调用 SetInterval 方法。客户端通过集线器连接。我也不希望 QueueProcessor 的另一个实例被实例化。
解决方案
我们解决这个问题的方法是将第三个服务作为单例添加到服务集合中。
这是完整的 PoC 示例:https ://github.com/doming-dev/SignalRBackgroundService
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<QueueProcessor>();
services.AddSingleton<HelperService>();
services.AddSignalR();
}
}
HelperService 引发后台服务可以锁定的事件。
public class HelperService : IHelperService
{
public event Action OnConnectedClient = delegate { };
public event Action<int> SpeedChangeRequested = delegate { };
public void OnConnected()
{
OnConnectedClient();
}
public void SetSpeed(int interval)
{
SpeedChangeRequested(interval);
}
}
现在,当客户端发送消息时,集线器可以调用 HelperService 上的方法,这反过来会引发后台服务正在处理的事件。
public class MyHub : Hub
{
private readonly IHelperService helperService;
public MyHub(IHelperService service)
{
helperService = service;
}
public override async Task OnConnectedAsync()
{
helperService.OnConnected();
await base.OnConnectedAsync();
}
public void SetSpeed(int interval)
{
helperService.SetSpeed(interval);
}
}