условия гонки в WCF с использованием не односторонних методов

StackOverflow https://stackoverflow.com/questions/472351

Вопрос

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

Допустим, у меня есть следующий код:

public interface IServer
{
  [OperationContract(IsOneWay = false)]
  [FaultContract(typeof(ChatException))]
  void BroadcastMessage(string msg);
}

public class Server : IServer 
{
  void BroadcastMessage(string msg) // I'm not mentionning the try/catch/throw FaultException here for readability purposes
  {
    foreach (IClientCallback c in callbacks){
      c.ReceiveMessage(msg);
    }

  }
}

public interface IClientCallback
{
  [OperationContract(IsOneWay = true)]
  void ReceiveMessage(string s);
}

И вот выдержка из конфигурации привязки :

<endpoint address="" 
binding="netTcpBinding" 
bindingConfiguration="DuplexBinding" 
contract="IServer" />

 <binding name="DuplexBinding" sendTimeout="00:01:00">
   <reliableSession ordered="true" inactivityTimeout="00:05:00" enabled="true"/>
   <security mode="None">
     <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
     <message clientCredentialType="Windows" />
   </security>
 </binding>

Это, конечно, какой-то псевдо-c #, я удалил много нерелевантного кода для большей ясности.

Теперь к делу :Этот код не будет работать.Когда я вызываю BroadcastMessage, метод никогда не возвращается, и в конечном итоге я получаю тайм-аут на стороне клиента.Если я отлаживаю на стороне сервера, все кажется нормальным (я возвращаюсь из метода BroadcastMessage точно так, как можно было бы ожидать, и я не блокирую любые односторонние вызовы ReceiveMessage)

Вот два способа исправить этот код :

  1. удалите FaultContract и объявите метод BroadcastMessage как oneway=true
  2. Транслируйте сообщение всем, КРОМЕ первоначального отправителя

Мое первое предположение состояло в том, что клиентская сторона ожидала возврата сервера и, следовательно, была недоступна для обработки входящего вызова ReceiveMessage с сервера, тем самым блокируя сервер, НО ReceiveMessage объявлен как oneway, и отладка сервера показывает, что он не блокируется при любом вызове ReceiveMessage

Теперь, мои вопросы :

  • Что происходит?

  • Есть ли другие способы исправить это?(может быть, настроив конфигурацию привязки ?)

  • Допустим, я выбираю исправление 2 (т. Е. не отправляю ответную трансляцию отправителю), что произойдет, если сервер вызовет мой обратный вызов ReceiveMessage (потому что кто-то другой отправил мне сообщение), пока я жду завершения моего собственного вызова BroadcastMessage?

  • Я читал, что односторонние вызовы не являются полностью односторонними, и что сервер все еще ожидает HTTP-ответа от другой стороны.Есть какие-нибудь подробности по этому поводу?в частности, может ли клиент отвечать на такие http-ответы, когда он заблокирован при удаленном вызове?

Редактировать:Консоль .net 3.5 на стороне сервера, Winforms .net 3.5 на стороне клиента

Это было полезно?

Решение

Это звучит как тупик, возможно, из-за контекста синхронизации.Что такое клиент?Winform?WPF?WCF уважает sync-context, что означает "переключиться на поток пользовательского интерфейса" для winforms и WPF.Если вы создание запрос на блокировку в потоке пользовательского интерфейса, затем игра окончена.

Попробуйте выполнить свой запрос WCF в фоновом потоке, чтобы поток пользовательского интерфейса был доступен для обслуживания входящего запроса;это может быть так же просто, как использование ThreadPool, или , может быть BackgroundWorker.

Другие советы

попробуйте добавить этот атрибут в вашу конкретную реализацию вашего сервиса:

[System.ServiceModel.ServiceBehavior(UseSynchronizationContext=false)]
public class Server : IServer {}

Во-вторых, попробуйте включить трассировку WCF, чтобы увидеть, происходит ли у вас что-то в недрах вашей реализации WCF, что доставляет вам огорчение.У меня было несколько действительно странных ошибок, которые имели смысл только тогда, когда я начал отслеживать и обнаружил ФАКТИЧЕСКОЕ сообщение об ошибке, которое возникало.

Отслеживание службы WCF

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top