Подтвердить что ты не робот

Обнаружение разъединения разъемов в WCF

Мы создаем сервер WCF (.NET 4.0). Он будет использовать только транспорт net.tcp.

Когда клиент закрывает TCP-соединение, сервер получает необработанное CommunicationException и завершается.

Q1. Как мне обрабатывать CommunicationException, чтобы сервер не прерывал работу и продолжал обслуживать других клиентов?

Q2. В обработчике, как мне получить SessionId сеанса, который был прерван? Мне нужно это, чтобы очистить некоторые данные, относящиеся к сеансу.

Спасибо заранее!

P.S. Соединение происходит через Интернет, поэтому сокет может быть закрыт в любое время, независимо от того, отключается ли клиент изящно или нет.

4b9b3361

Ответ 1

Любой канал WCF реализует ICommunicationObject, который предоставляет события для времени жизни канала.

Вы должны прослушать Faulted событие

Сессионный доступ можно получить, как всегда, из свойства OperationContext.Current.

Когда ваш клиент откроет канал (при первой операции), зарегистрируйтесь в соответствующие события:

OperationContext.Current.Channel.Faulted += new EventHandler(Channel_Faulted);
OperationContext.Current.Channel.Closed += new EventHandler(Channel_Faulted);

и

 void Channel_Faulted(object sender, EventArgs e)
 {
     Logout((IContextChannel)sender);
 }

 protected void Logout(IContextChannel channel)
 {
        string sessionId = null;

        if (channel != null)
        {
            sessionId = channel.SessionId;
        }
      [...]
 }

Ответ 2

ICommunicationObject obj = (ICommunicationObject)callback;
                obj.Closed += new EventHandler((a, b) => 
                {
                    if (list.Exists(cli => cli.CallbackService == (ITecnobelRemoteServiceCallback)a))
                    {
                        var query = (from cc in list where cc.CallbackService == (ITecnobelRemoteServiceCallback)a select cc).ToList();
                        query.ForEach(
                            delegate (Client ccc)
                            {
                                ccc.CallbackService = null;
                            });
                    }

                });