简体   繁体   中英

ASP.NET Core 3.1 - From a Hosted Service, check if client (Index) page is loaded

I have a simple 1-page web app using the VS2019 Razor Pages template. The hosted service will send data to the page via SignalR. Is it possible to check if the client page (Index page) is loaded because if not then the hosted service will pause sending data? When running from VS2019 the page of course opens automatically but running from "dotnet run" I need to know if the user has loaded the page into the browser eg they might shut it down after the service has started.

namespace TestProject
{
    public class TestService : IHostedService
    {
        public TestService(ILogger<TestService> logger)
        {
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            // HERE - check if index page is loaded - how??

            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            return Task.CompletedTask;
        }

    }
}

Implement simple SignalR connection counter

public class SignalRConnectionList
{
    private readonly object _sync = new object();
    private readonly List<string> _items = new List<string>();

    public void Remove(string connectionId)
    {
        lock (_sync)
        {
            _items.Remove(connectionId);
        }
    }

    public void Add(string connectionId)
    {
        lock (_sync)
        {
            _items.Add(connectionId);
        }
    }

    public int Count
    {
        get
        {
            lock (_sync)
            {
                return _items.Count;
            }
        }
    }
}

In ConfigureServices of Startup class add SignalRConnectionList as singleton

services.AddSingleton<SignalRConnectionList>();

Override OnConnectedAsync and OnDisconnectedAsync methods in Hub class

public class ChatHub: Hub
{
    public ChatHub(SignalRConnectionList connectionList)
    {
        ConnectionList = connectionList;
    }

    private SignalRConnectionList ConnectionList { get; }

    public override Task OnConnectedAsync()
    {
        ConnectionList.Add(Context.ConnectionId);
        return base.OnConnectedAsync();
    }

    public override Task OnDisconnectedAsync(Exception exception)
    {
        ConnectionList.Remove(Context.ConnectionId);
        return base.OnDisconnectedAsync(exception);
    }

Now in IHostedService you can use connection counter implemented above

public class SimpleService : BackgroundService
{
    public SimpleService(
        ILogger<SimpleService> logger,
        IHubContext<ChatHub> hubContext,
        SignalRConnectionList connectionList)
    {
        Logger = logger;
        HubContext = hubContext;
        ConnectionList = connectionList;
    }

    private SignalRConnectionList ConnectionList { get; }

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            await Task.Delay(1000, cancellationToken);
            if (ConnectionList.Count > 0)
            {
                await HubContext.Clients.All.SendAsync("ReceiveMessage", "system", "ping " + DateTime.Now, cancellationToken);
            }
        }
    }

In general you cannot answer the question check if index page is loaded in a web server. The server just serves content to clients that can do whatever they like with that content without the server being informed about the details.

However, if you have a SignalR connection from the client to the server you have state on the server for each connection. I think that is what you need to use to solve your problem.

You can override the OnConnectedAsync and OnDisconnectedAsync methods of your SignalR Hub to keep track of connections. This information can then be shared with your background service that uses IHubContext to send data to all clients (but only if there are any clients).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM