SignalR, push-уведомление подключенным клиентам на основе происходящего события делает Hub удаленным.

Я пытаюсь отправить уведомления клиентам, которые подключились к SignalR Hub, на основе связанных событий, происходящих в Asterisk Сервер PBX VOIP с использованием AsterNet ARI.

Я могу получать события с помощью класса DeviceStateChangedEvent из AsterNet, используя обработчик событий, и хочу отправлять клиентам уведомления, связанные с изменениями состояния их устройств.

Кроме того, соединение SignalR также работает, и на веб-странице клиента отображается приветственное сообщение.

Но проблема заключается в том, что при отправке уведомления методом SendAsync вызывающему клиенту мой концентратор удаляется, и ниже возникает исключение:

System.ObjectDisposedException: 'Невозможно получить доступ к удаленному объекту. Имя объекта: «AgentHub».

Вот мой класс Hub, в котором я переопределил метод OnConnectedAsync () для отправки приветственного сообщения и установки обработчика событий для прослушивания событий с АТС.

    public class AgentHub : Hub
    {
        public static AriClient ActionClient;

        public override async Task OnConnectedAsync()
        {
            ActionClient = new AriClient(
               new StasisEndpoint("voipserver", port, "username", "password"),
               "HelloWorld",
               true);

            ActionClient.Connect();

            ActionClient.OnDeviceStateChangedEvent += new DeviceStateChangedEventHandler(async delegate (IAriClient sender, DeviceStateChangedEvent e)
            {
                var notification = new DeviceStateChangeNotification
                {
                    NotificationText = e.Device_state.Name + "'s state changed to " + e.Device_state.State,
                    SentAt = DateTime.Now.ToString()
                };

                await Clients.Caller.SendAsync(
                    "ReceiveNotification",
                    notification.NotificationText,
                    notification.SentAt
                );
            });

            var notification = new DeviceStateChangeNotification
            {
                NotificationText = "Welcome!",
                SentAt = DateTime.Now.ToString()
            };

            await Clients.Caller.SendAsync(
                "ReceiveNotification",
                notification.NotificationText,
                notification.SentAt
            );

            await base.OnConnectedAsync();

        }
    }

person Mehdi    schedule 23.01.2020    source источник
comment
Не имеет отношения к проблеме с удалением вашего концентратора, но я думаю, что у вас будут проблемы с вашим ActionClient, потому что он статичен. OnConnectedAsyc вызывается для каждого пользователя, который подключается, и, поскольку ActionClient статичен, он будет перезаписываться каждый раз. Вероятно, у вас должен быть единственный обработчик событий, возможно, подписанный в конструкторе вашего концентратора, и отправка обработчика в Clients.All.   -  person Jeff Shepler    schedule 24.01.2020
comment
@JeffShepler спасибо, но та же ошибка с перемещением ARIClient в конструктор Hub. Я думаю, согласно github.com/aspnet/SignalR/issues/2424#issuecomment- 394198451 проблема в том, что у меня нет доступа к Hub извне.   -  person Mehdi    schedule 24.01.2020


Ответы (1)


Хабы недолговечны, они существуют только во время выполнения метода концентратора. Здесь происходит то, что вы создаете событие для OnDeviceStateChangedEvent, которое фиксирует «это» (концентратор). Позже, когда событие запускается, вы пытаетесь получить доступ к концентратору, который был удален сразу после выхода из метода.

Чтобы сделать это правильно, вам нужно ввести IHubContext<AgentHub> в конструктор концентратора, а затем сохранить его и Context.ConnectionId в своем событии.

И не используйте Context.ConnectionId непосредственно в своем мероприятии, потому что при этом будет зафиксировано «это» и возникнет та же проблема. Вместо этого вы можете создать переменную вне события внутри метода концентратора для хранения Context.ConnectionId и использования этой переменной внутри события.

person Brennan    schedule 24.01.2020