0

I have a WPF application that is communicating with a WCF server.

I am using one ChannelFactory to create channels for each call:

var channel = _channelFactory.CreateChannel();
var contextChannel = channel as ICommunicationObject;
try
  {
      channel.DoSomething();
  }
  catch (Exception)
  {
      contextChannel?.Abort();
      throw;
  }
  finally
  {
      contextChannel?.Close();
  }

There are many requests to the server when starting the application and at some points it grinds to an halt and I get timeouts. Looking at netstat I see a few ESTABLISHED connection to the server,

When I change the ServicePointManager.DefaultConnectionLimit to 10, I can process more calls to the server, but it still comes to a halt after some time with a timeout exception.

Setting ServicePointManager.DefaultConnectionLimit to int.MaxValue processes all my request, but I have about 720 ESTABLISHED connections to the server (netstat on the server gives me the same result).

I am confused about two things here:

  1. It looks like WCF is not pooling connections, but creating a new connection for each request
  2. Even after a I close the channel, the connection seems to remain established.

I also checked the ServicePointManager.FindServicePoint(new Uri("https://server:3000")); and it confirms that CurrentConnections are at the limit I set as the ServicePointManager.DefaultConnectionLimit.

I have reduced the ServicePointManager.MaxServicePointIdleTime to 500, this closes the connections faster, but it still creates a connection for each call I make.

How can I convince the channel factory to reuse exising channels when communicating with my server.

This is my binding:

new WebHttpBinding
{
    TransferMode = TransferMode.Streamed,
    ReceiveTimeout = TimeSpan.FromMinutes(1),
    SendTimeout = TimeSpan.FromMinutes(1),
    MaxReceivedMessageSize = 2147483647,
    MaxBufferPoolSize = 2147483647,
    ReaderQuotas =
        {
            MaxDepth = 2147483647,
            MaxStringContentLength = 2147483647,
            MaxArrayLength = 2147483647,
            MaxBytesPerRead = 2147483647,
            MaxNameTableCharCount = 2147483647
        },
    Security = new WebHttpSecurity() { Mode = WebHttpSecurityMode.Transport, Transport = new HttpTransportSecurity() { ClientCredentialType = HttpClientCredentialType.None } }
};
flayn
  • 5,272
  • 4
  • 48
  • 69

1 Answers1

0

Turns out that some of the streams that the server returns were not closed properly, which caused the client to keep the connection open, even after Close() was called.

If Close() is called and the stream that was returned to the client has not been closed, the connection will not be reused and the client will get a TimeoutException at some point.

Thanks to Zhang Lan for giving the hint in the MSDN forums: https://social.msdn.microsoft.com/Forums/vstudio/en-US/a91a6d05-05ae-402e-bf7d-306289c4d0e2/wcf-with-streaming-mode-timeout-after-two-calls-when-client-and-service-are-not-on-same-machine?forum=wcf

flayn
  • 5,272
  • 4
  • 48
  • 69
  • Did you use streams on the client side? If so, did closing the streams solve the problem? I've experienced i similar problem with open connections that I describe here https://stackoverflow.com/questions/59929665/can-creating-a-new-wcf-client-for-each-request-in-asp-net-core-lead-to-socket-ex I have no control over the service I call but as far as I know there are no streams involved. – Edminsson Feb 09 '20 at 12:29
  • Yes, my problem was caused by streams. I have attempted to answer your question, I hope that helps. – flayn Feb 09 '20 at 17:05