Jojo
Jojo

Reputation: 137

How do I push data from hub to client every second using SignalR

Working on building signalR hub, I'm able to get data from hub to the client but I'm, not sure how do I push it every 1 second.

I'm not sure where do I set the timer in the controller where getApps method exists or in the hub?

Hub:

public class nphub : Hub
{
    public readonly sbController _sbcontroller;

    public nphub(sbController sbcontroller)
    {
        _sbcontroller = sbcontroller;
    }

    public async Task NotifyConnection()
    {
        IActionResult result = await _sbcontroller.getApps();
        await Clients.All.SendAsync("TestBrodcasting", result);
    }
}

In Controller:

public async Task<IActionResult> getApps()
{
    // var request = new HttpRequestMessage(HttpMethod.Get, "apps");
    // var response = await _client_NP.SendAsync(request);
    // var json = await response.Content.ReadAsStringAsync();

    return Ok($"Testing a Basic HUB at {DateTime.Now.ToLocalTime()}");
}

Client:

let connection = new signalR.HubConnectionBuilder()
    .withUrl("/nphub").build();

connection.start().then(function () {
    TestConnection();
}).catch(function (err) {
    return console.error(err.toString());
});

function TestConnection() {
    connection.invoke("NotifyConnection").catch(function (err) {
        return console.error(err.toString());
    });
}

connection.on("TestBrodcasting", function (time) {
    document.getElementById('broadcastDiv').innerHTML = time.value;
    document.getElementById('broadcastDiv').style.display = "block";
});

Just for the test purpose to see realtime changes, I'm trying to return time. I'm able to see time on the client but it's not changing.

Upvotes: 0

Views: 2170

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239250

You need to use a hosted service, as described in the docs. Add a class like:

internal class SignalRTimedHostedService : IHostedService, IDisposable
{
    private readonly IHubContext<nphub> _hub;
    private readonly ILogger _logger;
    private Timer _timer;

    public SignalRTimedHostedService(IHubContext<nphub> hub, ILogger<SignalRTimedHostedService> logger)
    {
        _hub = hub;
        _logger = logger;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is starting.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero, 
            TimeSpan.FromSeconds(1));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        _logger.LogInformation("Timed Background Service is working.");
        // send message using _hub
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

Note: A hosted service lives in singleton scope. You can inject IHubContext<T> directly, though, because it too is in singleton scope.

Then in ConfigureServices:

services.AddHostedService<SignalRTimedHostedService>();

Upvotes: 1

Related Questions