signalR отслеживает подключенных пользователей

Мне нужно проверить, подключен ли еще конкретный пользователь.

У меня есть следующий 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?");
    }
}

НО как мне получить ответ от клиента?

РЕДАКТИРОВАТЬ: выполняемые шаги:

Мне нужно точное количество подключенных пользователей, потому что если есть хотя бы один подключенный пользователь, мне нужно запустить задачу. И я хочу убедиться, что для всех подключенных пользователей выполняется только 1 задача ‹2 (запускать задачу). предположим такую ​​ситуацию: 2 пользователя просматривают страницу, использующую signalR. HashSet теперь содержит 2 идентификатора, и задача выполняется. Один закрывает свой браузер, а через несколько секунд другой обновляет свой. Теперь первый (тот, который закрыл свой браузер, не выполнил метод OnDisconnected, поэтому HashSet все еще имеет свой ConnectionId, а тот, который "обновился", выполнил OnDisonnected, а затем OnConnected, который добавил его connectionId в HashSet. Поэтому вместо этого имея только 1 ConnectionId в HashSet и запуская задачу, HashSet содержит 2 (старый, больше не подключенный, и тот, который только что обновил его / ее браузер), и задача больше не запускалась.

Благодарность


person ShaneKm    schedule 04.03.2013    source источник


Ответы (2)


В SignalR 1.0 OnDisconnected всегда должен срабатывать, даже когда пользователи закрывают свое окно (за исключением перезапуска сервера).

OnDisconnected может не сработать немедленно, потому что, если клиент не «прерывает» соединение, это считается «нечистым», поскольку есть вероятность, что клиент может попытаться повторно подключиться (и если вы повторно подключитесь, вы не отключились в соответствии с семантикой SignalR) .

По умолчанию серверу требуется около 30 секунд для вызова OnDisconnected для «нечистого» разъединения. Это можно изменить с помощью GlobalHost.Configuration.DisconnectTimeout.

person halter73    schedule 04.03.2013
comment
Дело в том, что мне нужно точное количество подключенных пользователей, потому что если есть хотя бы один подключенный пользователь, мне нужно запустить задачу. И я хочу убедиться, что для всех подключенных пользователей выполняется только 1 задача ‹2 (запускать задачу). предположим такую ​​ситуацию: 2 пользователя просматривают страницу, использующую signalR. HashSet теперь содержит 2 идентификатора. Один закрывает свой браузер, а через несколько секунд другой обновляет свой. Теперь HasSet по-прежнему содержит 2 пользователя, и задача никогда не запускается. Как бы я это сделал ?? - person ShaneKm; 04.03.2013
comment
Каковы точные шаги воспроизведения? - person davidfowl; 04.03.2013
comment
похоже, это помогло: GlobalHost.Configuration.DisconnectTimeout. Я установил его на 1 секунду в своем global.asax. Благодарность - person ShaneKm; 06.03.2013

Я только что столкнулся с такой же ситуацией. 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», которое затем добавляется в список.

Надеюсь это поможет.

person Richard Harrison    schedule 04.05.2015