2014-08-26 6 views
6

У меня есть приложение 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() службы не попадает вообще.

+1

Основываясь на ваших симптомах, мне интересно, есть ли проблема с кодом обслуживания, а не с клиентом. Отладили ли вы службу, чтобы проверить, завершен ли сеанс с клиентом? Является ли ошибка, вызванная службой при запуске второго сеанса? –

+0

Это сложно проверить, потому что, как только отладчик подключен, проблема не возникает. Это похоже на то, что Visual Studio компенсирует проблемы и выполняет жесткую перезагрузку канала. – MrShoes

+1

'не завершает и не генерирует исключение', как это возможно? Код не просто берет сиесту в середине исполнения. –

ответ

1

Попробуйте закрыть завод вашего канала.

proxy.ChannelFactory.Close(); 
proxy.Close(); 
+0

Если вы посмотрите на Update 2, вы увидите, что метод Close фактически не завершается. – MrShoes

Смежные вопросы