Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are my message be processed out of order over a single WCF TCP channel (with ConcurrencyMode.Reentrant)?

Tags:

The client sends a lot of messages to the server from a single thread, over a single WCF channel.

The client sends the message with BeginMyMethod(x, b) as it does not wish to block while they get processed.

We have reliable messaging turned on, as we don’t wish to lose any messages, or have them get out of order.

However the messages are being despatched on multiple threads on the server, so are being process out of order.

We can’t have the server being single threaded, as we don’t wish a long running request from one client to block other clients.

So I just wish to process all the messages that come from a single client (over a single channel) in order with only one message from each cleint being processed at a time.

This would be easy for raw socket programming, however how to I get WCF to work as I wish?


I am now thinking that ConcurrencyMode.Reentrant does not behave well when used with InstanceContextMode.Single If I set use ConcurrencyMode.Single the messages are kept in order, but my call-backs deadlock.

(The test that gets the messages out of order has no callbacks and does not make any outgoing WCF calls, so I would expect ConcurrencyMode.Reentrant to behave the same as ConcurrencyMode.Single in that given test, but it does not)

I a not using any WCF config files, the code is:

serviceHost = new ServiceHost(this);
serviceHost.AddServiceEndpoint(
   typeof(IAllEngineManagersAsyncCallbacks),
   new NetTcpBinding(SecurityMode.None, true),
   endPointAddress);
like image 208
Ian Ringrose Avatar asked Feb 17 '10 13:02

Ian Ringrose


1 Answers

I have now worked round this problem by:

  • Changing all my call-backs from the server to the client to be OneWay
  • Using a dispatcher in the client before passing on any callback from the server, so client code never calls the sever from within a call-back
    • The client call-back object is marked with CallbackBehavior(UseSynchronizationContext=false, ConcurrencyMode=ConcurrencyMode.Single)
    • When running in Winform or WPF I use SynchronizationContext.Post to depatch the callbacks
    • When the cleint is a Console or a Windows server I use a custom depatcher.
  • So letting me use ConcurrencyMode.Single on both the server and the client.

It is now working as expected.
(BeginMyMethod(x, b) is still being used to send messaged from the client to the server)

(ConcurrencyMode.Reentrant seems to sometimes release the lock even when the WCF call is not made on the some thread that is processing the incoming message, it is just not a useful as Reentrant was in DCOM)

like image 97
Ian Ringrose Avatar answered Oct 11 '22 17:10

Ian Ringrose