Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do WCF Callbacks TimeOut

I've written a system that uses a Duplex NetTcp Channel with a callback to function as a publish/subscribe server.

Do I have to worry about the callback timing out if not connection is sent after a while or will the callback pipe be maintained indefinitely?

like image 278
Omar Kooheji Avatar asked May 14 '12 15:05

Omar Kooheji


People also ask

What do timeouts mean in WCF?

Furthermore, most of them have a slightly different meaning on the server-side and the client-side. That is a whole lot, so let’s discuss them one at a time. From the client’s point of view, those timeouts are pretty straightforward: WCF throws a TimeoutException if the communication channel cannot be opened/closed within the configured time span.

What are duplex callbacks in WCF?

Windows® Communication Foundation (WCF) supports this classic invocation model, but it also provides built-in support for two additional operation types: one-way calls for fire-and-forget operations and duplex callbacks that let the service call back to the client.

How does WCF handle idle time in client side?

It is completely ignored by WCF at the client-side (it has nothing to do with the time it takes to receive a response). The service host uses this timeout to determine when to drop idle connections. If no message is received within the configured time span the connection is closed.

What is the difference between receivetimeout and closetimeout?

This timeout also applies when sending reply messages from a callback contract method. OpenTimeout – used when opening channels when no explicit timeout value is specified. CloseTimeout – used when closing channels when no explicit timeout value is specified. ReceiveTimeout – is not used.


1 Answers

The callback won't be maintained indefinitely, It will look for the timeout values you've set in your config. If you enable reliable sessions then you can set the inactivity timeouts of your clients. You can configure timeouts like this:

 <netTcpBinding>
    <binding 
             closeTimeout="00:01:00"
             openTimeout="00:01:00" 
             receiveTimeout="00:10:00" 
             sendTimeout="00:01:00"
             transactionFlow="false" 
           ......>
        <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="true" />
    </binding>
  </netTcpBinding>

When these values are reached and there is still no response, your communication channel becomes faulted and you need to re-create a client proxy to consume the service. The default value for receiveTimeout is 10 minutes so you can increase that, but also make sure to increase your inactivityTimeout as well, your inactivityTimeout should be greater than your receiveTimeout.

EDIT:

You could keep changing your receiveTimeout programmatically based on values your client sends back to the server, the key is keeping the new timeout values same on the service and client. You would go about doing this on the client (an example I'm taking from a chat service I'm making with WCF and consuming with Silverlight clients):

//Create different clients dynamically
MyChatServiceClient _client1 = new MyChatServiceClient( "NetTcpBinding_IMyChatService_1");
MyChatServiceClient _client2 = new MyChatServiceClient( "NetTcpBinding_IMyChatService_2");

In the client configuration:

<!--In your config file, define multiple endpoints/behaviors with different values based on your needs-->
        <bindings>
            <customBinding>
                <binding name="NetTcpBinding_IMyChatService_1" receiveTimeout="00:01:00" ...>
                    <binaryMessageEncoding />
                    <tcpTransport maxReceivedMessageSize="283647" maxBufferSize="283647" />
                </binding>
                <binding name="NetTcpBinding_IMyChatService_2" receiveTimeout="00:22:00" ...>
                    <binaryMessageEncoding />
                    <tcpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
            </customBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://192.168.1.51:4520/VideoChatServer/"
                binding="customBinding" bindingConfiguration="NetTcpBinding_IMyChatService_1"
                contract="IMyChatService" name="NetTcpBinding_IMyChatService_1" />

          <endpoint address="net.tcp://192.168.1.51:4522/VideoChatServer/"
                binding="customBinding" bindingConfiguration="NetTcpBinding_IMyChatService_2"
                contract="IMyChatService" name="NetTcpBinding_IMyChatService_2" />
        </client>

So you can define multiple endpoints or bindings in the config on your client or your server, then based on whatever event in your application you can instantiate _clientProxyX to consume _serviceInstanceX which will have different binding/endpoint values but the same contract as your previous service instance. In the example above the first binding has a timeout of 1 minute, the second binding 2 minutes. An important point to consider is that if you wish to recreate new client proxies like this, then you need to tear down your old client proxy and crate a new one, which effectively disconnects your clients from the service, at least momentarily.

Also you can modify those values (openTimeout, closeTimeout etc.) programmatically on both the server when instantiating a new service host. You can create a new host, based on one of the binding configurations you've defined in your config, or create a new config programmatically, something like this:

var host = new ServiceHost(typeof(MyChatService));
            var webHttpBinding = new System.ServiceModel.WebHttpBinding();
            //Modify new timeout values before starting the host
            webHttpBinding.OpenTimeout = new TimeSpan(1, 0, 0);
            webHttpBinding.CloseTimeout = new TimeSpan(1, 0, 0);
            host.AddServiceEndpoint(webHttpBinding, "http://192.168.1.51/myService.svc");
            //start the host after necessary adjustments
            host.Open();

This looks quite messy I know, but the point is WCF gives you a lot of flexibility in being able to modify you binding configs programmatically. Be sure to check out this great answer on modifying your WCF config files. And you can also easily create a whole service configuration programmtically.

like image 104
Mohammad Sepahvand Avatar answered Oct 04 '22 09:10

Mohammad Sepahvand