Marco Mayer
Marco Mayer

Reputation: 337

Recommended lifecycle for services using SignalR hubs

I'm injecting following service with the SignalR ContentHub in various controllers in a ASP.NET Core web application (running on .NET Core 2.2). Currently the service is injected with a transient lifecycle. Using singleton lifecycle would be better? Is the transient lifecycle in this case a possible source for performance issues?

public class PushMessageService : IPushMessageService
{
    private readonly ILogger<PushMessageService> _logger;
    private readonly IHubContext<ContentHub> _context;

    public PushMessageService(
        ILogger<PushMessageService> logger,
        IHubContext<ContentHub> context
    )
    {
        _logger = logger;
        _context = context;
    }    

    public async Task Push(int productId)
    {
        var msg = new Message
        {
            ProductId = productId
        };

        await SendAsync("PushMsg", productId, msg);
    }

    private async Task SendAsync<TPayload>(string methodName, int productId, TPayload payload)
    {
        await _context.Clients.Group("prod" + productId).SendAsync(methodName, payload);
    }
}

Upvotes: 1

Views: 2968

Answers (2)

Chris Pratt
Chris Pratt

Reputation: 239440

The IHubContext abstraction that wraps the hub is a singleton. As such, the lifetime of the class using it as a dependency doesn't really matter. Whether you use a singleton, scoped, or transient lifetime, you always get the same instance.

Upvotes: 2

Kiril1512
Kiril1512

Reputation: 3611

SignalR expects the Hub to be created separately for each message. You need to add it as a Transient service if you want your Hub to be in DI. You generally shouldn't resolve the Hub out of DI. If you need to share code between your Hub and some other component, I'd suggest using either IHubContext or putting the shared code in a separate DI service as you doing here. So I believe that this should be a transient.

Upvotes: 0

Related Questions