5

我需要检查特定用户是否仍处于连接状态。

我有以下跟踪用户的 HashSet:

public static class UserHandler
{
    public static HashSet<string> ConnectedIds = new HashSet<string>();
}

所以断开连接:

    public override Task OnDisconnected()
    {
        UserHandler.ConnectedIds.Remove(this.Context.ConnectionId);
        if (UserHandler.ConnectedIds.Count == 0)
        {
               // STOP TASK -> SET CANCELLATION
        }
        return base.OnDisconnected();
    }

和连接:

    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();
    }

现在,当用户简单地关闭他/她的浏览器窗口时,问题就出现了。我无法知道他/她是否断开了连接。

所以基于这里的一些问题,我会打电话给每个客户并得到回复。我不知道该怎么做。

我想我会有这个:

public static void CheckConnectedUsers()
{
    var context = GlobalHost.ConnectionManager.GetHubContext<TaskActionStatus>();
    foreach (var connection in UserHandler.ConnectedIds)
    {
        context.Clients.Client(connection).verifyConnected("online?");
    }
}

但是我如何从客户那里得到回复?

编辑:执行的步骤:

我需要连接的用户的确切数量,因为如果至少有一个用户连接,我需要开始一项任务。我想确保所有连接的用户< 2(启动任务)只运行 1 个任务。假设这样的情况:2 个用户查看使用 signalR 的页面。HashSet 现在包含 2 个 ID,并且正在运行一个任务。一个人关闭他/她的浏览器,几秒钟后,另一个人刷新他/她的浏览器。现在,第一个(关闭他/她的浏览器的那个没有执行 OnDisconnected 方法,所以 HashSet 仍然有他/她的 ConnectionId,而“刷新”的那个确实执行了 OnDisonnected 然后 OnConnected 将他的 connectionId 添加到 HashSet。所以在 HashSet 中只有 1 个 ConnectionId 并开始一项任务,HashSet 包含 2 个(旧的不再连接和刚刚刷新他/她的浏览器的那个),

谢谢

4

2 回答 2

6

使用 SignalR 1.0,OnDisconnected应始终触发,即使用户关闭其窗口(如果服务器重新启动则例外)。

OnDisconnected可能不会立即触发,因为如果客户端没有“中止”连接,则认为它“不干净”,因为客户端可能会尝试重新连接(如果重新连接,根据 SignalR 的语义,您还没有断开连接)。

默认情况下,服务器调用OnDisconnected“不干净”断开连接大约需要 30 秒。这可以通过重新配置GlobalHost.Configuration.DisconnectTimeout

于 2013-03-04T16:02:59.457 回答
0

我刚刚遇到了同样的情况。onDisconnect 并不总是被触发。我的解决方案是偶尔轮询用户以查看他们是否仍处于连接状态。

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

因此,集线器每 5 秒向用户列表中的所有客户端发送一次,然后清除列表。

如果客户端收到“areYouThere”消息,它会回复“imHere”,然后将其添加到列表中。

希望这可以帮助。

于 2015-05-04T21:11:17.783 回答