Как отписаться от сервиса WCF

1

Мне удалось запустить службу WCF с обратными вызовами. Клиент просто "подписывается" на услугу, и служба запускает таймер. Этот таймер определяет, когда вызывать функцию обратного вызова.

Теперь мой вопрос заключается в том, как отказаться от подписки на клиента, потому что просто закрытие клиента вызывает CommunicationException.

Является ли моя реализация Unsubscribe() отключением таймера или я должен выполнить дополнительные шаги?

Здесь мой класс обслуживания:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.PerSession)]
internal class HostFunctions : IHostFunctions
{
    private static ILog _log = LogManager.GetLogger(typeof(HostFunctions));
    private IHostFunctionsCallback _callback;
    private Timer _timer;

    #region Implementation of IHostFunctions

    public void Subscribe()
    {
        _callback = OperationContext.Current.GetCallbackChannel<IHostFunctionsCallback>();
        _timer = new Timer(1000);
        _timer.Elapsed += OnTimerElapsed;
        _timer.Enabled = true;
    }

    public void Unsubscribe()
    {
        _timer.Enabled = false;
    }

    private void OnTimerElapsed(object sender, ElapsedEventArgs e)
    {
        if (_callback == null) return;
        try
        {
            _callback.OnCallback();
        }
        catch (CommunicationException comEx)
        {
            // Log: Client was closed or has crashed
            _timer.Enabled = false;
        }
    }

    #endregion
}
Теги:
callback
wcf

1 ответ

1
Лучший ответ

В вашем случае вам не нужно выполнять дополнительные шаги. Поскольку ваши клиенты получают собственный экземпляр службы, канал обратного вызова выходит из области действия, когда клиентский канал закрывается. (Примечание: это так, потому что режим экземпляра службы - за сеанс)

Поэтому вам нужно только вызвать Close() на клиентском канале от клиента, и все выйдет за пределы области обслуживания. Не забудьте закрыть канал правильно:

try
{
    channel.Close();
}
catch
{
    channel.Abort();
    throw;
}

Либо это, либо дождаться, когда время ожидания приема услуги будет превышено, а затем сеанс закончится, и канал выйдет за пределы области. Это немного расточительно, однако, поскольку служба будет оставаться в памяти на сервере дольше.

Обратите внимание, что нет необходимости называть Close/Dispose на канале обратного вызова со стороны службы.

  • 0
    А что произойдет, если клиент выйдет из строя или его процесс будет убит? В этом случае клиент не может закрыть соединение.
  • 0
    Тогда клиентский канал в конечном итоге прекратит работу и закроется сам.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню