My WCF service uses netTcpBinding, and has a callback object.
I need to service multiple concurrent clients, and mantain sessions, so the service is decorated with
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple]
To avoid thread deadlocks, the callback class is decorated with
[CallbackBehavior(UseSynchronizationContext=false)]
and I use SynchronizationContext
to execute the method in the UI thread.
The problem is that sometimes the channel gest closed with no reason (ICommunicationObject.Closing
event gets fired). After that, I get exceptions in any subsequent service call.
Looking in the trace file, the last message is a callback call, however, the callback method never gets invoked. There are no exceptions.
After some debugging I identified that this happens only when the callback call is made in the middle of a synchronous operation. The steps would be this:
- Call to service method
A
with IsOneWay=true
- Call to service method
B
with IsOneWay=false
A
invokes a callback method, but B
is still executing.
This shouldn't be a problem because the callback has UseSynchronizationContext=false
, so the callback call could be attended in a separate thread.
I was unable to reproduce the problem in a simpler scenario. Following these steps in a simple project executes successfully.
Any idea of what could be happening or how to identify the problem?
I think what's probably happening is the client is faulting the channel because it received the callback message when it was expecting the reply message. In WCF with net.tcp, callbacks and replies use the same channel.
As a rule, you should never call a callback method inside the body of a request/reply (IsOneWay=false) OperationContract method. The safest thing would be to not have any request/reply methods in your contract whatsoever when doing duplex, but you can safely have them just so long as they don't call back into the callback contract before returning. (It would be ok to call a callback method after returning, for example from another worker thread).
You should add this attribute on the top of WCF wrapper class:
[CallbackBehavior(UseSynchronizationContext=false)]
From cauldwell.net:
The problem, it turned out, was that ASP.NET uses (by default) a little thing called the SynchronizationContext. As near as I can tell
(I haven't researched this thoroughly, to be honest) one of it's jobs
it to make sure that any callbacks get run on the UI thread, thereby
obviating the need to call Control.Invoke like you do in WinForms. In
my case, that additional lock was giving something fits, and it was
trying to clean stuff up on a thread that wasn't around any more,
hence to NullReferenceException.
Thanks for the response!
I could solve the error.
It was a serialization problem, I added IncludeExceptionsInFaults=true
in the service and callback behavior attribute, and then I was able to see the error.
The problem was that I was sending a DataTable with columns of type object.