Run BackgroundService with parameter from code

How I can run BackgroundService by parameter from code?

I have SignalR, user join to group (example group:a, group:b, group:c, group:d). I want run CatService with current join group:

public class CatHub : Hub
{
    public async Task JoinToGroup(string group)
    {
        // how i can run new CatService with current group ??? 
        CORE_RUN_NEW_SERVICE<CatService>(_, group);
    }
}

public class CatService : BackgroundService
{
    private readonly IHubContext<CatHub> _hub;
    private readonly string _group;  
    public CandleSig(IHubContext<CatHub> hub, string group)
    {
        _hub = hub;
        _group = group
    }

    protected override Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            _hub.SendToGroup(_group, "test")
            await Task.Delay(TimeSpan.FromMinutes(1), ct);
        }
    }
}

2 answers

  • answered 2021-01-17 10:54 Florian

    As far as I know, modifiying the service collection after starting the application is not supported, so starting a further BackgroundService isn't possible.

  • answered 2021-01-17 22:33 Stephen Cleary

    You cannot modify the number of background services once the application is running.

    However, you can create a single background service that has a queue. First define the queue:

    public sealed class MyBackgroundQueue
    {
      private readonly Channel<string> _channel = Channel.CreateUnbounded<string>();
    
      public ValueTask QueueAsync(string item) => _channel.WriteAsync(item);
    
      public IAsyncEnumerable<T> DequeueAllAsync(CancellationToken ct) =>
          _channel.ReadAllAsync(ct);
    }
    

    inject it into your background service:

    public class CatService : BackgroundService
    {
      private readonly IHubContext<CatHub> _hub;
      private readonly MyBackgroundQueue _queue;
      public CatService(IHubContext<CatHub> hub, MyBackgroundQueue queue)
      {
        _hub = hub;
        _queue = queue;
      }
    
      protected override Task ExecuteAsync(CancellationToken ct)
      {
        await foreach (var item in _queue.DequeueAllAsync(ct);
          _hub.SendToGroup(_group, "test")
      }
    }
    

    and also into your hub:

    public class CatHub : Hub
    {
      private readonly MyBackgroundQueue _queue;
      public CatHub(MyBackgroundQueue queue) => _queue = queue;
    
      public async Task JoinToGroup(string group)
      {
        await _queue.EnqueueAsync(group);
      }
    }