Дуплексный канал WCF закрывается при использовании обратных вызовов - PullRequest
1 голос
/ 18 ноября 2009

Моя служба WCF использует netTcpBinding и имеет объект обратного вызова.

Мне нужно обслуживать несколько одновременных клиентов и обслуживать сессии, поэтому служба украшена

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple]

Чтобы избежать взаимоблокировок потоков, класс обратного вызова украшен

[CallbackBehavior(UseSynchronizationContext=false)]

и я использую SynchronizationContext для выполнения метода в потоке пользовательского интерфейса.

Проблема в том, что иногда жест канала закрывается без причины (событие ICommunicationObject.Closing запускается). После этого я получаю исключения при любом последующем обращении в службу поддержки.

Глядя в файл трассировки, последнее сообщение является обратным вызовом, однако метод обратного вызова никогда не вызывается. Исключений нет.

После некоторой отладки я обнаружил, что это происходит только тогда, когда выполняется обратный вызов в середине синхронной операции. Шаги будут такими:

  1. Вызов метода обслуживания A с IsOneWay=true
  2. Вызов метода обслуживания B с IsOneWay=false
  3. A вызывает метод обратного вызова, но B все еще выполняется.

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

Мне не удалось воспроизвести проблему в более простом сценарии. Выполнение этих шагов в простом проекте выполняется успешно.

Есть идеи, что может происходить или как определить проблему?

Ответы [ 3 ]

10 голосов
/ 20 ноября 2009

Я думаю, что, вероятно, происходит то, что клиент отказывает каналу, потому что он получил сообщение обратного вызова, когда ожидал ответное сообщение. В WCF с net.tcp обратные вызовы и ответы используют один и тот же канал.

Как правило, вы никогда не должны вызывать метод обратного вызова внутри тела запроса / ответа (IsOneWay = false) метода OperationContract. Самым безопасным было бы отсутствие каких-либо методов запроса / ответа в контракте при выполнении дуплекса, но вы можете безопасно их использовать, лишь бы они не перезванивали в контракт обратного вызова перед возвратом. (Было бы нормально вызвать метод обратного вызова после возврата , например, из другого рабочего потока).

0 голосов
/ 11 июля 2012

Вы должны добавить этот атрибут в начало класса-оболочки WCF:

[CallbackBehavior(UseSynchronizationContext=false)]

от cauldwell.net:

Проблема, как оказалось, заключалась в том, что ASP.NET использует (по умолчанию) небольшую вещь, называемую SynchronizationContext. Насколько я могу судить (Я не исследовал это полностью, если честно) одна из его работ чтобы убедиться, что все обратные вызовы запускаются в потоке пользовательского интерфейса, тем самым избавляя от необходимости вызывать Control.Invoke, как вы делаете в WinForms. В в моем случае этот дополнительный замок давал что-то подходящее, и это было пытаясь навести порядок в нити, которой больше не было, следовательно, к NullReferenceException.

0 голосов
/ 25 ноября 2009

Спасибо за ответ! Я мог бы решить ошибку.

Это была проблема с сериализацией, я добавил IncludeExceptionsInFaults=true в атрибуте обслуживания и поведения обратного вызова, а затем смог увидеть ошибку.

Проблема заключалась в том, что я отправлял таблицу данных со столбцами типа объекта.

...