У меня есть приложение SOA, которое использует дуплексную службу WCF, размещенную в службе Windows. Сам клиент является приложением WPF.Необычное поведение клиента WCF
Я вижу необычное поведение при закрытии и перезапуске клиентского приложения. Если я запустил новый экземпляр после его закрытия, ничего видимого не произойдет. Однако проверка диспетчера задач показывает, что новый экземпляр работает как фоновый процесс. Если я попытаюсь запустить новый экземпляр клиентского приложения, он отобразит экран ошибки, который я написал, - сообщив об ошибке в службе. Исследование показало, что клиент не может создать новый экземпляр канала обратного вызова службы, поскольку другое приложение уже зарегистрировало URL-адрес. Это System.ServiceModel.AddressAlreadyInUseException.
Если я завершаю задачу фонового клиента в диспетчере задач, мой клиент, отображающий сообщение об ошибке, сможет подключиться к службе и работать как обычно. Я также заметил, что если я закрою фоновую задачу перед запуском нового экземпляра, новый экземпляр также не появится.
Моя забота здесь в том, что это неприменимо и представляет собой настоящую проблему для пользователей. Что может пойти не так? Кажется, что что-то не очищает неуправляемый ресурс, но я использовал ANTS и не могу его идентифицировать. Клиент создан как:
IServiceCallback callback = new Callback();
_context = new InstanceContext(callback);
_channelFactory = new DuplexChannelFactory<IMyService>(_context, binding, endpoint);
_proxy =
_channelFactory.CreateChannel();
((ICommunicationObject)_proxy).Open(TimeSpan.FromSeconds(5));
Конструктор Service использует следующий код:
_callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
commObject.Faulted += ChannelFaulted;
commObject.Closing += ChannelClosing;
commObject.Closed += ChannelClosed;
}
OperationContext.Current.Channel.Faulted += ChannelFaulted;
OperationContext.Current.Channel.Closed += ChannelFaulted;
Перед закрытием, клиент вызывает метод Disconnect сервиса, который делает:
var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
commObject.Faulted -= ChannelFaulted;
commObject.Closing -= ChannelClosing;
commObject.Closed -= ChannelClosed;
}
OperationContext.Current.Channel.Faulted -= ChannelFaulted;
OperationContext.Current.Channel.Closed -= ChannelFaulted;
Наконец , клиент закрывает каналы следующим образом:
foreach (var incomingChannel in _context.IncomingChannels.ToArray())
{
incomingChannel.Close();
}
try
{
var proxy = _proxy as IChannel;
if (proxy != null)
{
proxy.Close();
}
}
catch (Exception)
{
_channelFactory.Abort();
}
Почему я вижу это необычное поведение? Есть ли что-то, что мне не хватает, чтобы закрыть канал или что-то, что я делаю неправильно, чтобы создать его? Или, может быть, в моем коде должна быть проблема, которая поддерживает канал или сеанс?
** ОБНОВЛЕНИЕ: ** Я пробовал несколько вещей и выяснил, что если я запустил экземпляр клиента, закройте его, а затем оставьте его на час, я могу запустить другой экземпляр без проблем. Я также обнаружил, что если я перезапущу службу Windows после создания и закрытия экземпляра клиентского приложения, то я также могу создать другое в этих обстоятельствах.
** ОБНОВЛЕНИЕ 2: ** Поступая, я вижу, что входящий канал.Close() не завершается и не выдает ошибку. Я удалил этот раздел, а также нашел proxy.Close() не завершил и не выбрал исключение. Я попытался использовать перегрузки и добавил тайм-аут, но исключение таймаута не выбрасывается. Метод Dispose() службы не попадает вообще.
Основываясь на ваших симптомах, мне интересно, есть ли проблема с кодом обслуживания, а не с клиентом. Отладили ли вы службу, чтобы проверить, завершен ли сеанс с клиентом? Является ли ошибка, вызванная службой при запуске второго сеанса? –
Это сложно проверить, потому что, как только отладчик подключен, проблема не возникает. Это похоже на то, что Visual Studio компенсирует проблемы и выполняет жесткую перезагрузку канала. – MrShoes
'не завершает и не генерирует исключение', как это возможно? Код не просто берет сиесту в середине исполнения. –