问题
I need to check whether a specific user is still connected.
I have the following HashSet that keeps track of users:
public static class UserHandler
{
public static HashSet<string> ConnectedIds = new HashSet<string>();
}
So on disconnected:
public override Task OnDisconnected()
{
UserHandler.ConnectedIds.Remove(this.Context.ConnectionId);
if (UserHandler.ConnectedIds.Count == 0)
{
// STOP TASK -> SET CANCELLATION
}
return base.OnDisconnected();
}
and on Connected:
public override Task OnConnected()
{
Logger.Log.file.Info("[TaskActionStatus HUB => OnConnected] Start");
UserHandler.ConnectedIds.Add(this.Context.ConnectionId);
// start task only if at least one listener
if (UserHandler.ConnectedIds.Count < 2)
{
// START A TASK -> (WHILE LOOP THAT GETS DATA FROM DB EVERY 2 SEC)
}
return base.OnConnected();
}
Now, the problem arises when a users simply closes his/her browser window. There is no way for me to know if he/she disconnected.
So based on some question here, I would call each client and get a response. I'm not sure how to do it.
I guess I would have this:
public static void CheckConnectedUsers()
{
var context = GlobalHost.ConnectionManager.GetHubContext<TaskActionStatus>();
foreach (var connection in UserHandler.ConnectedIds)
{
context.Clients.Client(connection).verifyConnected("online?");
}
}
BUT how do I get a response back form the client?
EDIT: steps that are executed:
I need the exact number of users connected because If there is at least one user connected I need to start a task. And I want to ensure that only 1 task is running for all connected users < 2 (start a task). suppose a situation like this: 2 users view a page that is using signalR. HashSet now contains 2 ids and a task is running. One closes his/her browser and after a few seconds and another refreshes his/hers. Now, the first one (the one that closed his/her browser did not execute OnDisconnected method so HashSet still has his/her ConnectionId, and the one that "refreshed" did execute OnDisonnected and then OnConnected which added his connectionId to HashSet. So instead of having only 1 ConnectionId in a HashSet and starting a task, HashSet contains 2 (old-not connected anymore and the one that just refreshed his/her browser), and the task never got started again.
thanks
回答1:
With SignalR 1.0, OnDisconnected
should always fire, even when users close their window (the exception to this being if the server restarts).
OnDisconnected
may not fire immediately, because if the client doesn't "abort" the connection it is considered "unclean" since there is a chance the client may try and reconnect (and if you reconnect you haven't disconnected according to SignalR's semantics).
By default, it should take about 30 seconds for the server to call OnDisconnected
for an "unclean" disconnect. This can be reconfigured via GlobalHost.Configuration.DisconnectTimeout
.
回答2:
I have just come across this same situation. The onDisconnect is not always fired. My solution was to poll the users occasionally to see if they are still connected.
Public Sub checkconnections()
For Each s In users
Clients.User(s).areYouThere()
Next
users = New List(Of String)
System.Threading.Thread.Sleep(5000)
checkconnections()
End Sub
Public Sub imHere()
Dim id = GetClientId()
If Not users.Contains(id) Then
users.Add(id)
End If
Clients.All.sendCount(count)
End Sub
so every 5 seconds the hub sends to all clients in the users list then clears the list.
If the client receives the 'areYouThere' message it replies with 'imHere' which then gets added in to the list.
Hope this helps.
来源:https://stackoverflow.com/questions/15203141/signalr-tracking-connected-users