简体   繁体   中英

Memory leak in DirectorySearcher loop

I am using DirectorySearcher in a using statement to loop through about 5000 objects. It appears through troubleshooting that the PropertiesToLoad property is causing a massive memory leak. My program goes from 0 to 2 GB of memory used in no time flat if I set the propertiesToLoad property on each object. In this manner the search is very fast but has the memory leak.

If I set the PropertiesToLoad at the beginning and not on each loop the memory leak does not occur but the search is slow. I have tried clearing the Properties on each loop which fixes the memory leak but again causes the search to slowdown. I am hoping to find the best of both worlds here.

NOTE: My app is Multi-Threaded so the AD search is happening on 10 threads at once.

using (DirectorySearcher mySearcher = new DirectorySearcher(new DirectoryEntry("LDAP://rootDSE", null, null, AuthenticationTypes.FastBind)))
            { 
                        try
                        {
                            mySearcher.Filter = ("(&(objectClass=user)(sAMAccountName=" + object + "))");
                            mySearcher.SearchScope = SearchScope.Subtree;
                            mySearcher.CacheResults = false;
                            mySearcher.PropertiesToLoad.AddRange(new string[] { "canonicalName", "displayName", "userAccountControl" });

                            foreach (SearchResult result in mySearcher.FindAll())
                            {
                                try
                                {
                                    shareInfo.displayname = result.Properties["displayName"][0].ToString();
                                }
                                catch
                                {
                                    shareInfo.displayname = "N/A";
                                }

                                shareInfo.canName = result.Properties["canonicalName"][0].ToString();

                                int userAccountControl = Convert.ToInt32(result.Properties["userAccountControl"][0]);
                                bool disabled = ((userAccountControl & 2) > 0);
                                if (disabled == true)
                                    shareInfo.acctstatus = "Disabled";
                                else
                                    shareInfo.acctstatus = "Enabled";
                            }
                        }
                        catch
                        {

                        }
            }  

Here's something I learned just a few weeks ago from the documentation for the FindAll method :

Due to implementation restrictions, the SearchResultCollection class cannot release all of its unmanaged resources when it is garbage collected. To prevent a memory leak, you must call the Dispose method when the SearchResultCollection object is no longer needed.

You're using using on the DirectorySearcher , but not on the result collection. Try assigning the resulting collection to a variable that can be disposed later:

using (var results = mySearcher.FindAll())
{
    foreach (SearchResult result in results)
    {
        ...
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM