Print Queue State Every 10 seconds C# SignalR

35 Views Asked by At

I am learning SignalR and need your help. In the following code, you can see one of the hubs of my first project. In this hub, I create a Queue and fill it using the JoinQueue method. Now I am looking for a technique to print the number of members in the Queue on the console every 5 seconds. I need a way to manage queue outside this hub I guess.

using BackEnd.Model;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace BackEnd.Hubs
{
    public class QueueHub : Hub
    {
        private Queue<QueueItem> userQueue = new Queue<QueueItem>();

        public async Task JoinQueue(string userToken)
        {
            QueueItem user = new QueueItem
            {
                UserToken = userToken,
                ConnectionString = Context.ConnectionId
            };

            userQueue.Enqueue(user);

            Console.WriteLine(userQueue.Count);
        }

        public override Task OnConnectedAsync()
        {
            string connectionId = Context.ConnectionId;
            Console.WriteLine($"{connectionId} is Connected to the server");
            return base.OnConnectedAsync();
        }
    }
1

There are 1 best solutions below

0
Jason Pan On BEST ANSWER

Using Background Service, it can help you implement this requirement.

Here is the test result in my side.

enter image description here

The structure of my test project.

enter image description here

QueueMonitorService.cs

using WebApplication2.IServices;

namespace WebApplication2.BackgroundServices
{
    public class QueueMonitorService : BackgroundService
    {
        private readonly IQueueManager _queueManager;

        public QueueMonitorService(IQueueManager queueManager)
        {
            _queueManager = queueManager;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                Console.WriteLine(DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")+$"   The number of members in the queue: {_queueManager?.UserQueue?.Count}");
                await Task.Delay(5000, stoppingToken);
            }
        }
    }
}

QueueHub.cs

using Microsoft.AspNetCore.SignalR;
using WebApplication2.IServices;

namespace WebApplication2.Hubs
{
    public class QueueHub : Hub
    {
        private readonly IQueueManager _queueManager;

        public QueueHub(IQueueManager queueManager)
        {
            _queueManager = queueManager;
        }

        public Task AddToQueue(string userToken)
        {
            _queueManager.JoinQueue(userToken, Context.ConnectionId);
            return Task.CompletedTask;
        }
        public override Task OnConnectedAsync()
        {
            string connectionId = Context.ConnectionId;
            Console.WriteLine($"{connectionId} is Connected to the server");
            return base.OnConnectedAsync();
        }
    }
}

IQueueManager.cs

using WebApplication2.Models;

namespace WebApplication2.IServices
{
    public interface IQueueManager
    {
        Queue<QueueItem>? UserQueue { get; }
        void JoinQueue(string userToken, string connectionId);
    }
}

QueueItem.cs

namespace WebApplication2.Models
{
    public class QueueItem
    {
        public string? UserToken { get; set; }
        public string? ConnectionString { get; set; }
    }
}

QueueManager.cs

using WebApplication2.IServices;
using WebApplication2.Models;

namespace WebApplication2.Services
{
    public class QueueManager : IQueueManager
    {
        public Queue<QueueItem> UserQueue { get; } = new Queue<QueueItem>();

        public void JoinQueue(string userToken, string connectionId)
        {
            QueueItem user = new QueueItem
            {
                UserToken = userToken,
                ConnectionString = connectionId
            };

            UserQueue.Enqueue(user);
            Console.WriteLine(UserQueue.Count);
        }
    }
}

The last step, we need to register it in the Program.cs file.

builder.Services.AddSingleton<IQueueManager, QueueManager>(); 
builder.Services.AddHostedService<QueueMonitorService>(); 
builder.Services.AddSignalR();