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.


person dom-dev    schedule 18.04.2019    source источник


Ответы (2)


Мы решили эту проблему, добавив третью службу в коллекцию служб как синглтон.

Вот полный пример 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);
    }
}
person dom-dev    schedule 19.04.2019

Вам не нужен другой экземпляр QueueProcessor. Клиент может легко вызвать SetIntervalSpeed ​​из своего кода. Документация с примером.

var connection = new signalR.HubConnectionBuilder().withUrl("/autocommithub").build();
connection.invoke("SetIntervalSpeed", interval)

SignalR предоставляет API для создания межклиентского RFC.

person Sviatoslav V.    schedule 23.04.2019
comment
Это вызывает метод на концентраторе, но мне нужно было вызвать методы в фоновой службе через концентратор. - person dom-dev; 24.04.2019