I’ve got a ServiceHost in a service app that communicates with 1700 clients every 60 second. When I start the service, it climbs to about 1500 open handles almost immediately, then continues to add another 300 after about 5 minutes (and continues onward continuously after that.)
I’ve looked at ProcessExplorer and in Split view, it shows hundreds of handles of type File named “Device\Afd” – which is a representative of the TCP socket being used to communicate (I believe).
I’m only assuming that my handle leak is related to the ServiceHost because it represents the highest number of handles observed from Process Explorer. What I’m wondering is why doesn’t the service close these? Do I need to set a timeout of some sort or do I need to actively close them myself somewhere?
Here’s how my ServiceHost is created:
wcfObject = new WcfObject();
host = new ServiceHost(wcfObject, baseWcfAddress);
ServiceBehaviorAttribute attribute = (ServiceBehaviorAttribute)host.Description.Behaviors[typeof(ServiceBehaviorAttribute)];
attribute.ConcurrencyMode = ConcurrencyMode.Multiple;
attribute.InstanceContextMode = InstanceContextMode.Single;
And in my app.config:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfObject" behaviorConfiguration="DefaultBehavior">
<host>
<baseAddresses >
<!-- Defined in code -->
</baseAddresses>
</host>
<endpoint name="NetTcpEndPoint" address="" binding="netTcpBinding" bindingConfiguration="netTcpBinding" contract="IWcfObject"/>
<endpoint name="NetTcpMetadataPoint" address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="netTcpBinding" maxReceivedMessageSize="9655360" maxBufferSize="9655360" maxBufferPoolSize="524288">
<readerQuotas maxArrayLength = "932000" maxStringContentLength="900000" maxDepth="32"/>
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior" >
<serviceMetadata httpGetEnabled="False" httpGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="True"/>
<serviceThrottling maxConcurrentCalls="50" maxConcurrentSessions="100" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
As it turns out, I was running my service from a [STAThread] – anytime an app uses COM calls, you’ll potentially leak memory unless you are running [MTAThread] mode.