Search code examples
c#timeoutwcf-binding

WCF erratically timing out despite binding timeout settings


My system is composed of a bunch of WCF services that can be used by various clients.
The first thing I do is to run the services in interactive mode (I have a console popping and letting me know the service is started).
I can then run a given client that excercises any of my WCF services. When instantiated the client create a channel and associated timeouts in the following way:

var ctx = new InstanceContext(TestCallbackProxy.Instance);

string baseAddress = Constants.ServiceBaseAddress;

var binding = new NetNamedPipeBinding();
binding.MaxConnections = 10;
binding.OpenTimeout = System.TimeSpan.FromMinutes(1);
binding.CloseTimeout = System.TimeSpan.FromMinutes(1);
binding.ReceiveTimeout = System.TimeSpan.FromMinutes(5);
binding.SendTimeout = System.TimeSpan.FromMinutes(5);

var channelFactory = new DuplexChannelFactory<ITestService>(ctx, binding, new EndpointAddress(baseAddress + serviceName));

 // Create channel to a specified endpoint
 _channel = channelFactory.CreateChannel() as ITestService;

Now, the service eventually times out when left unused for a while, which from my understanding is expected. ie. The channel will simply vanish/be discarded by the system if unused - Something to do with reusablility and optimisation I believe.
However, when trying to prove this theory and reducing all the timeouts, I cannot get the service to break. ie. Should the service not timeout/break when trying to use it when left alone for more than 30sec? Used timeouts are:

binding.OpenTimeout = System.TimeSpan.FromMinutes(0.5);
binding.CloseTimeout = System.TimeSpan.FromMinutes(0.5);
binding.ReceiveTimeout = System.TimeSpan.FromMinutes(0.5);
binding.SendTimeout = System.TimeSpan.FromMinutes(0.5);

Solution

  • I think the reason is that you should be setting your timeouts on the service side, where you are setting up your hosts and defining endpoints, not on the client side. Here is an example:

    var binding = new NetNamedPipeBinding();
    binding.MaxConnections = 10;
    binding.OpenTimeout = TimeSpan.FromMinutes(0.5);
    binding.CloseTimeout = TimeSpan.FromMinutes(0.5);
    binding.ReceiveTimeout = TimeSpan.FromMinutes(0.5);
    binding.SendTimeout = TimeSpan.FromMinutes(0.5);
    
    // Compose URIs
    Uri uriBase = new Uri(baseAddress);
    Uri uri = new Uri(baseAddress + something);
    Uri uriMex = new Uri(baseAddress + something + "/mex");
    
    // Create End Points
    SomeHost = new CustomServiceHost(typeof(TestService), uriBase);
    SomeHost.AddServiceEndpoint(typeof(ITestService), binding, uri);
    SomeHost.AddServiceEndpoint(typeof(IMetadataExchange), binding, uriMex);
    
    // Open the ServiceHost
    SomeHost.Open();
    

    Now you should see you service dying after 30sec.