Why is my WCF client disconnected after a method call on the WCF server that raises the event?

I have a WCF service hosted in a windows service. There is an s method in the WCF service that will raise an event that is signed by the Windows service. When an event is raised and the Windows service catches it, the Windows service calls another WCF method to send a message to all connected clients. For some reason, when I have all this happening in this sequence, an error occurs:

This request operation sent to http://localhost:8731/Design_Time_Addresses/WCF/WCFService/ did not receive a reply within the configured timeout (00:00:29.9939996).... 

Here is the relevant code from the WCF service:

 public event EventHandler<CustomEventArgs> CustomEvent; private static readonly List<IMessageCallback> subscribers = new List<IMessageCallback>(); public void SendMessageToClients(string msgType, string message) { subscribers.ForEach(delegate(IMessageCallback callback) { if (((ICommunicationObject)callback).State == CommunicationState.Opened) { callback.OnMessageReceived(msgType, message, DateTime.Now); } else { subscribers.Remove(callback); } }); } public bool messageHost() { try { if (CustomEvent != null) CustomEvent(null, new CustomEventArgs()); return true; } catch { return false; } } 

And the code from the Windows service:

 wcfService = new WCF.WCFService(); sHost = new ServiceHost(wcfService); wcfService.CustomEvent += new EventHandler<WCF.CustomEventArgs>(wcfService_CustomEvent); sHost.Open(); private void wcfService_CustomEvent(object source, WCF.CustomEventArgs e) { wcfService.SendMessageToClients("log", "CLient connected!!"); osae.AddToLog("client message"); //just writes to a log file } 

And the client just calls it:

 wcfObj.messageHost(); 

Here is the client configuration:

  <system.serviceModel> <bindings> <wsDualHttpBinding> <binding name="WSDualHttpBinding_IWCFService" closeTimeout="00:00:10" openTimeout="00:00:10" receiveTimeout="00:10:00" sendTimeout="00:00:30" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" /> <security mode="Message"> <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" /> </security> </binding> </wsDualHttpBinding> </bindings> <client> <endpoint address="http://localhost:8731/Design_Time_Addresses/WCF/WCFService/" binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IWCFService" contract="WCFService.IWCFService" name="WSDualHttpBinding_IWCFService"> <identity> <dns value="localhost" /> </identity> </endpoint> </client> 

And the config service:

 <system.serviceModel> <services> <service name="WCF.WCFService" behaviorConfiguration="WCFBehavior"> <endpoint address="" binding="wsDualHttpBinding" contract="WCF.IWCFService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="" contract="IMetadataExchange"/> <host> <baseAddresses> <add baseAddress="http://localhost:8731/Design_Time_Addresses/WCF/WCFService/" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="WCFBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors> 

If I remove the SendMessageToClients call from an event in the Windows service, it works and just logs the “client message” as expected. In addition, when an error occurs due to a timeout, I can click Continue, and the client will continue to execute, and he received a message from the host. Why is strange behavior happening?

EDIT: Mark led me to search in the right place: http://www.codeproject.com/KB/WCF/WCF_Duplex_UI_Threads.aspx

+4
source share
1 answer

The symptoms here tell me that there is a dead end, possibly due to a synchronous context (by default, WCF synchronizes the context). Meaning: An external message expects access to a context, but it is itself what expects an existing context.

The easiest way to learn this is to execute an external message in a workflow:

 ThreadPool.QueueUserWorkItem(delegate { wcfObj.messageHost(); }); 

I believe that you can also configure WCF to change how it approaches sync-context, but I don’t remember how ...

+3
source

All Articles