Мне удалось запустить службу 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
}
В вашем случае вам не нужно выполнять дополнительные шаги. Поскольку ваши клиенты получают собственный экземпляр службы, канал обратного вызова выходит из области действия, когда клиентский канал закрывается. (Примечание: это так, потому что режим экземпляра службы - за сеанс)
Поэтому вам нужно только вызвать Close() на клиентском канале от клиента, и все выйдет за пределы области обслуживания. Не забудьте закрыть канал правильно:
try
{
channel.Close();
}
catch
{
channel.Abort();
throw;
}
Либо это, либо дождаться, когда время ожидания приема услуги будет превышено, а затем сеанс закончится, и канал выйдет за пределы области. Это немного расточительно, однако, поскольку служба будет оставаться в памяти на сервере дольше.
Обратите внимание, что нет необходимости называть Close/Dispose на канале обратного вызова со стороны службы.