I have one WCF site that I’m managing and it started leaking memory, which ended up consuming up all server memory and stopped working.
The change I made between the incident was that I changed from using service reference to using a class called WebServcieClinet that dynamically instantiating the web service connection.
The reason why I introduced WebServiceClient is that I wanted to dynamically change the web service endpoint.
What I have missed from the class that creates the web service connection was failing to release the unmanaged resource.
Unmanaged resource in C# is such as open file, open connection, etc., which garbage collector does not know about. For this unmanaged resource, we need to release the resource explicitly by calling Dispose () method.
Ref: http://stackoverflow.com/questions/3433197/what-exactly-are-unmanaged-resources
1. Calling GC.Collect after finishing using the unmanaged resource.
At first, I tried to go use GC.Collect, which means that I explicitly called garbage collection method to release any resource that’s not being used anymore.
WebServicesClient dm = new WebServicesClient(requestData.token, Settings.Default.EndPointUrl); // do something dm = null; GC.Collect();
This seems sort or work, but not perfect. And also I could find that calling GC.Collect is very costly in terms of performance.
2. Use IDisposible pattern
All web service connections (XXXSoapClient) made by the WebServiceClient object are unmanaged resources and those are the object inherited from IDispoable for this reason.
So, I applied IDisposable interface in WebServiceClient.
public class WebServicesClient : IDisposable { bool disposed; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposed) return; if (disposing) { // Free any other manage object here. } // Free any unmanaged object here. if (soapClientA != null) { soapClientA.Close(); ((IDisposable) soapClientA).Dispose(); soapClientA = null; } if (soapClientB != null) { soapClientB.Close(); ((IDisposable) soapClientB).Dispose(); soapClientBA = null; } disposed = true; } // This is needed only when this object directly uses managed resources ~WebServiceClient() { Dispose(false); } }
When using the WebServiceClient, we can just call Dispose() instead of calling GC.Collect.
WebServicesClient dm = new WebServicesClient(requestData.token, Settings.Default.EndPointUrl); // do something dm.Dispose();
As the Dispose() method releases the exact resource that needs to be released, which is much efficient in terms of performance compared to calling GC.Collect, which investigate all resources that are still being used or not.
After applying IDisposable pattern, there wasn’t memory leak and performance should be ok.
3. Further clean up
I haven’t tested below, but what Dispose() does in web service base class is ‘Close’ the web service connection. In this regard, the line below may be redundant from the code of WebServiceClient.
soapClientA.Close();
Ref: http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface/538238#538238
http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface