0
votes

I have a WCF service and I defined a operation contract method called IsAlive(). The goal is to check if the client is still alive or not before the exceution of its callback function.

      if (IsClientAlive())
                        WcfService.Callback.UIMessageOnCallback(UIMessage);

The default timeout is set to 1 minute, too long in my case. As everything happens in the same workstation, I would like to reduce it to 5 seconds so there is only a little delay in the execution.

Following the instructions here https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/configuring-timeout-values-on-a-binding

I modified my app.config accordingly, but the nothing changed afterwards. The IsAlive() function keeps taking 1 minute to finalize. Any idea what am I missing?

<?xml version="1.0" encoding="utf-8" ?><configuration>
<startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>  <system.serviceModel>
<bindings>
  <wsHttpBinding>
    <binding openTimeout="00:00:05"
             closeTimeout="00:00:05"
             sendTimeout="00:00:05"
             receiveTimeout="00:01:00">
    </binding>
  </wsHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<services>
  <service name="EEAS.Kiosk.WcfService">
    <endpoint address="" binding="wsDualHttpBinding" contract="EEAS.Kiosk.IWcfService">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8733/KioskService/WcfService/" />
      </baseAddresses>
    </host>
  </service>
</services>  </system.serviceModel></configuration>

NOTE: I had a mispelling "wsHttpBinding" when it had to be "wsDualHttpBinding". Thanks stuardt for the tip! I did the change but IsAlive() function always thrown an exception "sessionful channel timed out".

{System.ServiceModel.CommunicationObjectAbortedException: The operation 'IsAlive' could not be completed because the sessionful channel timed out waiting to receive a message. To increase the timeout, either set the receiveTimeout property on the binding in your configuration file, or set the ReceiveTimeout property on the Binding directly.

So I put the ReceiveTimeout timeout back to 1 minute but the error persists. Any idea what could be happening? I checked the variable host.State and its value is CommunicationState.Opened.

1
Could be because you're setting the values on wsHttpBinding but actually using wsDualHttpBindingstuartd
Considering everything is localhost you should use either namedpipe or TCP bindingMickyD
@stuartd . thanks for the quick answer. I just saw it too. But now I have a different issue, the connection always gets a timeout. I increased up to 25 seconds but at some point the IsAlive function returns false. It seems like the client drops connection after the defined timeout.YaKs

1 Answers

0
votes

This explanation gave me the final tip. https://www.rauch.io/2015/06/25/all-wcf-timeouts-explained/

So I implemented a heartbeat in the client using a timer every 15 seconds. The receiveTimeout is set to 1 minute so it could miss 3 heartbeat before dropping the connection.

in the main method of the client:

       System.Timers.Timer keepAliveTimer = new System.Timers.Timer(15000);
        keepAliveTimer.AutoReset = false;
        keepAliveTimer.Elapsed += new System.Timers.ElapsedEventHandler(keepAliveTimer_Elapsed);
        keepAliveTimer.Start();

and the function which calls the isAlive method in the WCF service.

        void keepAliveTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        try
        {
            client.isAlive();
        }
        catch (System.Exception ex)
        {
            eventLog1.WriteEntry(" [CRITICAL EXCEPTION in keepAliveTimer_Elapsed()]. WCf service is down, Kiosk Tray Agent is trying to send a heartbeat." + Environment.NewLine + "Caught an exception of type" + ex.GetType().Name, EventLogEntryType.Error, 912);
        }
        finally
        {
            ((System.Timers.Timer)sender).Start();
        }
    }