SignalR 仅在用户关闭 page/tab 后才调用 OnDisconnect

SignalR call OnDisconnect only after user closing the page/tab

所以我正在使用 signalR 来列出在线用户。 我使用 stopCalled 来避免页面刷新就像断开连接一样,但现在用户永远不会断开连接..

public override Task OnDisconnected(bool stopCalled)
{
    var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
    var currentUser = manager.FindByName(Context.User.Identity.Name);
    string name = currentUser.NickName;
    if (!(stopCalled))
    {
        var item = users.SingleOrDefault(x => x.Nick == name);
        if (item != null)
            users.Remove(item);
        userNames.Remove(name);
        Clients.All.hubReceived(users);
    }     
    return base.OnDisconnected(stopCalled);
}

用户应该只在点击按钮(注销按钮)时断开连接 或者当他关闭 tab/page 时。 我能做什么?

stopCalled 指示客户端是否 disconnected gracefully or not,因此您当前的方法将仅删除那些连接消失的用户(例如:网络中断)。

对于所有在线用户的列表,计算每个用户的连接数。

OnConnected

  • 如果在列表中找不到该用户,请使用count = 1
  • 添加该用户
  • 如果用户在列表中,则增加计数

OnDisconnected

  • 减少该用户的计数
  • 如果该用户 count = 0,从列表中删除该用户

如果一个用户在线,那么他打开了多少window并不重要。 您应该通过他们的连接跟踪在线用户 in database.

如果用户刷新 window,您将创建一个新连接,因此之前的连接最终会断开连接。

类似这样,我猜猜你应该编码什么。

您应该在数据库 OnlineUser 中创建一个 table,其中包含列 ConnectionIdUserId

public override Task OnConnected()
{
    var onlineUserManager = NewOnlineUserManager<OnlineUser>(new OnlineUserStore<OnlineUser>(new ApplicationDbContext()));
    var onlineUser = onlineUserManager.FindByConnectionId(Context.ConnectionId);

    if (onlineUser == null)
    {
        var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        var currentUser = manager.FindByName(Context.User.Identity.Name);

        onlineUser = new OnlineUser
        {
            ConnectionId = Context.ConnectionId,
            UserId = currentUser.Id
        };

        onlineUserManager.Save(onlineUser);
    }

    return base.OnConnected();
}

public override Task OnDisconnected(bool stopCalled)
{
    if (stopCalled)
    {
        var onlineUserManager = NewOnlineUserManager<OnlineUser>(new OnlineUserStore<OnlineUser>(new ApplicationDbContext()));
        var onlineUser = onlineUserManager.FindByConnectionId(Context.ConnectionId);

        if (onlineUser != null)
        {
            onlineUserManager.Remove(onlineUser);
        }
    }

    return base.OnDisconnected(stopCalled);
}

您可能需要进行一些更改以支持一个用户的多个连接。