Почему мое сообщение не обрабатывается по одному каналу TCP WCF (с ConcurrencyMode.Reentrant)? - PullRequest
5 голосов
/ 17 февраля 2010

Клиент отправляет много сообщений на сервер из одного потока по одному каналу WCF.

Клиент отправляет сообщение с BeginMyMethod (x, b), так как он не хочет блокировать во время обработки.

У нас включен надежный обмен сообщениями, так как мы не хотим терять какие-либо сообщения или выводить их из строя.

Однако сообщения отправляются в несколько потоков на сервере, поэтому они обрабатываются не по порядку.

У нас не может быть однопоточного сервера, поскольку мы не хотим, чтобы длительный запрос от одного клиента блокировал других клиентов .

Так что я просто хочу обработать все сообщения, которые приходят от одного клиента (по одному каналу ) в порядке с только одним сообщение от каждого обрабатываемого клиента за один раз.

Это было бы легко для программирования сырых сокетов, однако как мне заставить WCF работать так, как я хочу?


Теперь я думаю, что ConcurrencyMode.Reentrant не работает должным образом при использовании с InstanceContextMode.Single Если я установил использование ConcurrencyMode.Single, то сообщения сохраняются в порядке, но мои обратные вызовы тупиковые.

(Тест, который выводит сообщения из строя, не имеет обратных вызовов и не делает никаких исходящих вызовов WCF, поэтому я ожидаю, что ConcurrencyMode.Reentrant будет вести себя так же, как ConcurrencyMode.Single в данном тесте, но это не так)

Я не использую файлы конфигурации WCF, код:

serviceHost = new ServiceHost(this);
serviceHost.AddServiceEndpoint(
   typeof(IAllEngineManagersAsyncCallbacks),
   new NetTcpBinding(SecurityMode.None, true),
   endPointAddress);

Ответы [ 3 ]

3 голосов
/ 25 февраля 2010

Я обошел эту проблему:

  • Изменение всех моих обратных вызовов с сервера на клиент на OneWay
  • Использование диспетчера в клиенте перед передачей любого обратного вызова с сервера, поэтому клиентский код никогда не вызывает сервер из обратного вызова
    • Объект обратного вызова клиента помечен с помощью CallbackBehavior ( UseSynchronizationContext = false , ConcurrencyMode = ConcurrencyMode.Single)
    • При работе в Winform или WPF я использую SynchronizationContext. Post для отправки обратных вызовов
    • Когда клиент является консолью или сервером Windows, я использую настраиваемый диспетчер .
  • Итак, позвольте мне использовать ConcurrencyMode.Single как на сервере, так и на клиенте.

Теперь он работает как положено.
(BeginMyMethod (x, b) все еще используется для отправки сообщений от клиента на сервер)

(ConcurrencyMode.Reentrant, кажется, иногда снимает блокировку, даже если вызов WCF не сделан в некотором потоке, который обрабатывает входящее сообщение, это просто бесполезно, поскольку Reentrant был в DCOM)

2 голосов
/ 17 февраля 2010

Если вы используете сгенерированные асинхронные методы BeginXXX, они выполняются в потоке ThreadPool.Поэтому, хотя вы отправляете сообщения в определенном порядке, никто не гарантирует, в каком порядке ThreadPool выполняет запросы.

0 голосов
/ 17 февраля 2010

Я думаю, что режим Reentrant подразумевает, что вы разрешаете обрабатывать сообщения не по порядку. Нормальным поведением такой службы было бы: получить сообщение, поместить в очередь для обработки внутренними потоками и, когда это сделано, уведомить клиента о результате. Так что, возможно, ваша служба получает сообщения в правильном порядке, но некоторые из них быстрее обрабатываются и возвращаются раньше, чем другие?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...