WCF callback not invoked on the client-side and hangs on the server-side

.net, c#, callback, wcf

Solution

You may to make sure that you add "ConcurrencyMode.Multiple" to the "CallbackBehavior" attribute on the class that implements the callback.

[CallbackBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)] 

Callback ConcurrencyMode reference: http://blogs.msdn.com/b/dsnotes/archive/2013/09/18/wcf-callback-operations-are-invoked-sequentially.aspx

In addition, if you have not already, you may want to consider enabling WCF tracing to ensure the server is really calling the client callback method.

WCF Tracing reference: http://msdn.microsoft.com/en-us/library/ms733025.aspx

Problem

I have a WCF service which works absolutely fine with regards to regular client->server calls. However I have attempted to introduce a simple callback into the service but it is not working... ultimately I am not sure where I have gone wrong so let me show you the set up and tell you what I do know. 1) Contracts ``` public interface IPIRSCallbackService { [OperationContract] void OnCallback(); } [ServiceContract(CallbackContract = typeof(IPIRSCallbackService))] public interface IPIRSService { etc... ``` 2) Server Contract Implementation NOTE: I check the state of callback channel and it is "opened" - not sure how much this is worth though. ``` [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)] class PIRSService : IPIRSService { public PIRSService() { callback = OperationContext.Current.GetCallbackChannel<IPIRSCallbackService>(); var x = ((ICommunicationObject)callback).State; callback.OnCallback(); // HANGS HERE } etc. ``` 3) Client - creating the proxy Now, this is probably not the common way you will see because I am using a ViewModelLocator to inject the service into my viewmodels... but I am sure this isn't causing the problem... and note that the normal service calls work absolutely fine. ViewModelLocator registering the service instances ``` SimpleIoc.Default.Register<PIRSService>(() => { IPIRSCallbackService callback = new PIRSCallbackService(); InstanceContext context = new InstanceContext(callback); return new PIRSService(context, "PIRSClient"); }, true); SimpleIoc.Default.Register<IPIRSService>(() => { return SimpleIoc.Default.GetInstance<PIRSService>(); }, true); ``` 4) Connecting to the service ``` DuplexChannelFactory<IPIRSService> channelFactory = new DuplexChannelFactory<IPIRSService>(callbackContext, endpointConfigName); channelFactory.Credentials.UserName.UserName = userName; channelFactory.Credentials.UserName.Password = password; proxy = channelFactory.CreateChannel(); ((IClientChannel)proxy).Open(); ``` 5) Client - endpoint configuration ``` <endpoint address="net.tcp://localhost:20437/PIRSService" binding="netTcpBinding" bindingConfiguration="StandardNetTcpBinding" contract="PIRS_Common.Service.IPIRSService" name="PIRSClient" kind="" endpointConfiguration="" behaviorConfiguration="CustomBehavior"> <identity> <dns value="WCfServer" /> </identity> </endpoint> ``` So, I don't know why the client-side implementation of the callback contract isn't fired... and consequently the server side call to the callback method hangs on the calls... as it is waiting for the callback to be completed. I am sure it is an issue with the callback not being registered correctly... but I am not sure what I am doing wrong. Do I need to register the call back contract on the client-side endpoint or anywhere else?

Original source