Step 2 Release the memory properly.
As I said in last post "
It sounds simple, but not because CLR is supposed to take care of the memory stuff. It works as a memory manager for .Net application, right? Something must be wrong if CLR can not do its job well which means somewhere in your code breaks the default garbage collection rules. "
It is confirmed there is memory leak in one public method after several rounds of tests. I spent almost one hour to stare at this piece of code and no progress. I even doubt my tests because this project is big and I need mock up some code to filter the suspicious method. I might be wrong when doing this thing. It turns out what I have done is ok after reviewing the record. So you know it is important to write down whatever tests you did.
So now the piece of code is here.
using System.DirectoryServices;
****
public List
DoSomething()
{
List
results = new List();
using (DirectorySearcher searcher = new DirectorySearcher(new DirectoryEntry(DefinedObject2.Instance.Path), "some string"))
{
foreach (SearchResult result in searcher.FindAll())
{
using (DirectoryEntry someObject = result.GetDirectoryEntry())
{
results.Add(new DefinedObject3( Get Something information from 'someObject' to construct this object ));
}
}
}
return results;
}
Take a while to guess what code leaks memory. Do not need doubt the logic. The method works fine.
I did more tests in this method. Tried different things including mocking up some pieces of code. But I did not doubt the libraries from .Net until I got nothing more to try. So I just add some Dispose() method to the objects which implements IDisposable(). Magically it worked. Tests show that memory usage is much much better. Now I got a clue how to fix them but still do not know why it works since CLR is supposed to take care of the memory usage.
More tests are done during this stage to help figure out exactly where to use Dispose(). It turns out objects under namespace System.DirectoryServices are all suspicious and need call Dispose() explicitly . I am not sure if every object under that namespace needs do it but I am sure System.DirectoryServices.SearchResultCollection and System.DirectoryServices.DirectoryEntry definitely need call dispose() explicitly. Did not get enough time to test every object under that namespace. So I just simply call Dispose() to every object under that namespace and implement IDisposable().
The final code looks like this
using System.DirectoryServices;
****
public List DoSomething()
{
List results = new List();
using (DirectoryEntry temp = new DirectoryEntry(DefinedObject2.Instance.Path))
{
using (DirectorySearcher searcher = new DirectorySearcher(temp, "some string"))
{
using (DirectorySearchCollections tempCollection = searcher.FindAll())
{
foreach (SearchResult result in tempCollection)
{
using (DirectoryEntry someObject = result.GetDirectoryEntry())
{
results.Add(new DefinedObject3( Get Something information from 'someObject' to construct this object ));
}
}
}
}
}
return results;
}