условия гонки в WCF с использованием односторонних методов - PullRequest
2 голосов
/ 23 января 2009

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

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

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 объявляется как односторонний и отлаживает сервер показывает, что он не блокирует ни один вызов ReceiveMessage

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

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

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

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

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

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

Ответы [ 2 ]

2 голосов
/ 23 января 2009

Звучит как тупик, возможно, из-за контекста синхронизации. Какой клиент? Winform? WPF? WCF учитывает синхронизирующий контекст, что означает «переключение на поток пользовательского интерфейса» для winforms и WPF. Если вы делаете запрос на блокировку в потоке пользовательского интерфейса, то игра окончена.

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

1 голос
/ 23 января 2009

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

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

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

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

...