Get number of listeners, clients connected to SignalR hub
There is no way to get this count from SignalR as such. You have to use the OnConnect()
and OnDisconnect()
methods on the Hub to keep the count yourself.
Simple example with a static class to hold the count:
public static class UserHandler
{
public static HashSet<string> ConnectedIds = new HashSet<string>();
}
public class MyHub : Hub
{
public override Task OnConnectedAsync()
{
UserHandler.ConnectedIds.Add(Context.ConnectionId);
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
UserHandler.ConnectedIds.Remove(Context.ConnectionId);
return base.OnDisconnectedAsync(exception);
}
}
You then get the count from UserHandler.ConnectedIds.Count
.
Count and list connectees in SignalR
Absolutely there is a way.
A lot of people handle this by creating a singleton class that contains a concurrent dictionary of any custom user object you define. If you add your custom user objects to this dictionary on connection and remove them on disconnection, you'll be able to query your dictionary for a count of active users. Please keep in mind that it may not be up to the second accurate, because there is roughly a 30 second "abort" window that may still be active, even if the client no longer is because they closed their browser.
Now, is there any real "hardbaked" functionality in SignalR to do this for you? Not that I'm aware, but I haven't looked into 2.0 too exhaustively yet. As for detecting disconnections, it is fairly robust and if a connection is not detected, it will remove the connection as mentioned, allowing you to keep on top of the disconnections.
There is an excellent tutorial describing this approach here:
http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-server-broadcast-with-signalr-20
SignalR send duplicate message to same user n times n is number of users connected .NetCore
as you have mentioned, the problem is RegisterNotification
is being called everytime an instance of MessageHub
is created. Instead of this, you can create background service and register to SqlDependency
there and send the events using IHubContext
. And after every notification, you call RegisterNotification
again, which might cause the duplication as well.
- https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services
- https://learn.microsoft.com/en-us/aspnet/core/signalr/hubcontext
I haven't tested this code, but here is an example:
public class EventBroadcaster : IHostedService
{
private readonly IHubContext<MessageHub> _hubContext;
private readonly string _connectionString;
public EventBroadcaster(
IConfiguration configuration,
IHubContext<MessageHub> hubContext)
{
_hubContext = hubContext;
_connectionString = // Get Connection String from configuration
}
public Task StartAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Started event broadcasting service");
RegisterNotification();
return Task.CompletedTask;
}
public void RegisterNotification()
{
using (SqlConnection con = new SqlConnection(_connectionString))
{
SqlCommand cmd = new SqlCommand(sqlCommand, con);
if (con.State != System.Data.ConnectionState.Open)
{
con.Open();
}
cmd.Notification = null;
SqlDependency sqlDep = new SqlDependency(cmd);
sqlDep.OnChange += sqlDep_OnChange;
using (SqlDataReader reader = cmd.ExecuteReader())
{
// nothing need to add here now
}
}
}
static int count = 1;
private async void sqlDep_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change )
{
SqlDependency sqlDep = sender as SqlDependency;
sqlDep.OnChange -= sqlDep_OnChange;
await _hubContext.Clients.User("64ed09d7-255f-4aae-a25f-7a50e59943b4").SendAsync("abc", "hello"+count);
count += 1;
}
}
public Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Event Broadcasting Service is stopping.");
// TODO: Stop listening to SqlDependency notifications
return Task.CompletedTask;
}
Show connected ids of clients in a Gridview or a listbox winform using SIgnalR
Try to remove the first and second line in your button2_Click method. You already added the connectionIds to your UserHandler instance in your overridden OnConnected method.
//edit
I have not changed anything at your code. I don't know how you still get an error.
//edit
You already have the connectionIds in your list? Why not using them? This will add the connectionIds to your datagrid. If you need more information like the username you could replace ConnectedIds in your UserHandler with a class with two properties username and connectionId.
if (UserHandler.ConnectedIds.Count != 0)
{
foreach(var connectionId in UserHandler.ConnectedIds)
{
dataGridView1.Rows.Add(connectionId);
}
}
Related Topics
How to Add a Line Break in C# .Net Documentation
What Replaces Wcf in .Net Core
What Do Programmers Mean When They Say, "Code Against an Interface, Not an Object."
Open File Dialog and Select a File Using Wpf Controls and C#
Post Build Event Execute Powershell
How to Add a String to a String[] Array? There's No .Add Function
Getting All Changes Made to an Object in the Entity Framework
+= New Eventhandler(Method) VS += Method
Differencebetween a C# Reference and a Pointer
Getting Downloads Folder in C#
What Method in the String Class Returns Only the First N Characters
How to Compare Unicode Characters That "Look Alike"
String.Isnullorempty(String) VS. String.Isnullorwhitespace(String)
C#: Convert Byte Array into a Float
Using Datetime in a SQLparameter for Stored Procedure, Format Error