Best Practice with WCF ChannelFactory and connection timeout

11,717

Solution 1

If you want to reuse an existing channel you need to Keep the channel alive by pinging the service every 9 minutes.I think the default receive timeout is 10 minutes, so the channel will be disconnected if it is kept idle beyond this.Or you can use reliable sessions to keep channels alive.

If you don't need to callback on the same channel , it is better you close the channel once you are done and recreate a new channel for every service operation.It is not expensive to create channels.You can cache the channel factory , but create channels for every call.

Solution 2

I know this question is quite old now but I see it didn't really get answered. There are two timeouts (well only 1 if you don't use reliable messaging) you should be concerned with when it comes to channels timing out. On the service side you have the "ReceiveTimeout" which is fired if no application messages are received within the timeout period. The default for this timeout is 10 minutes.

There is also the "InactivityTimeout" which is only used if "ReliableSession" is enabled. This timeout is the maximum duration that the channel allows the other communicating party not to send any messages before faulting the channel.

To increase the lifetime of your channel I recommend you enable "ReliableSession" and then set both your "ReceiveTimeout" & "InactivityTimeout" to a higher value. ReliableSession keeps the channel alive by sending ILM's (infrastructure level messages) like keep-alive's (ack's are also sent). If a keep-alive or an ALM (application level message) is not received before the "InactivityTimeout" expires the channel will fault.

Furthermore if an ALM (application level message) has not been received before the "ReceiveTimeout" expires the channel will fault.

So, it is recommended to either increase both timeouts to the same value OR set the "ReceiveTimeout" to a higher value than the "InactivityTimeout".

A side note, setting the "ReceiveTimeout" will have no effect when set on the client side, it is a service side timeout only. But when using ReliableSession on the service side, the client also has to implement it like so:

NetTcpBinding binding = new NetTcpBinding
        {
            ReliableSession = { Enabled = true },             
            SendTimeout = TimeSpan.FromMinutes( 1 )
        };

        binding.ReliableSession.InactivityTimeout = TimeSpan.Parse( "24.20:31:23.6470000" );

And the app.config on the service side would look something like this:

<bindings>
    <netTcpBinding>
      <binding name="netTestTcpBinding"
               receiveTimeout="24.20:31:23.6470000">
        <reliableSession inactivityTimeout="24.20:31:23.6470000"
                         enabled="true" />
      </binding>
    </netTcpBinding>
  </bindings>
<services>
  <service>
    <endpoint address="IServiceContract"
              binding="netTcpBinding"
              bindingConfiguration="netTestTcpBinding"
              name="serviceContractTcpBinding"/>
    <host>
        <baseAddresses>
             <add baseAddress="net.tcp://localhost:12001/" />
        </baseAddresses>
     </host>
    </service>                   
</services>
Share:
11,717
econner
Author by

econner

Updated on June 08, 2022

Comments

  • econner
    econner almost 2 years

    I am working on an winform application that will access a WCF service self-hosted as a windows service. I am using the ChannelFactory instead of the service reference. I have been successful in connecting and calling the WCF service. The issue is when I let the application remain idle for 20 minutes and then try to make another call. I receive the following error:

    "The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:59.9489970'."

    I am looking for the best practice on managing the connection. I currently have created a function called PrepareWCFConnection (see below) that checks state of the channel and the ChannelFactory. I call this method before I make any calls to the WCF services. Is there a better way of handling this?

         public bool PrepareWCFConnection()
        {
            if ((channelFactory == null) || 
                (channelFactory.State == CommunicationState.Faulted) ||
                (channelFactory.State != CommunicationState.Opened))
            {
                channelFactory = new ChannelFactory<IService1>(new NetTcpBinding(), endpointAddress);
            }
    
    
            if ((proxy == null) ||
                (((IClientChannel)proxy).State == CommunicationState.Faulted) ||
                (((IClientChannel)proxy).State != CommunicationState.Opened))
            {
                proxy = channelFactory.CreateChannel(endpointAddress);
                ((IClientChannel)proxy).Open();
            }
    
            return true;
        }
    
  • baraban
    baraban about 10 years
    good point: You can cache the channel factory , but create channels for every call.