Dispose not working as expected in DirectorySearcher

六月ゝ 毕业季﹏ 提交于 2019-12-11 03:43:39

问题


I am trying to connect and do simple functionalities such as search on an Active Directory using C#. However, I am stuck in a problem. I am using DirectorySearcher to search the directory. There are loads of entries in the directory.

This is the function

void RunThis()
{
        DirectoryEntry de = new DirectoryEntry();
        de.Path = "LDAP://" + domainName;
        de.Username = username;
        de.Password = password;
        de.AuthenticationType = AuthenticationTypes.Secure;

        DirectorySearcher deSearch = new DirectorySearcher(de);
        //Skipping properties to load
        try
        {
            deSearch.SearchScope = SearchScope.Subtree;
            SearchResultCollection rescoll = deSearch.FindAll();
            deSearch.Dispose();
            rescoll.Dispose();
        }
        catch (Exception obj)
        {
            System.Console.WriteLine("Exception in getting results. {0}",obj.Message);
        }

     }
     de.Dispose();

} // end of function 

This is a sample function I trimmed down to. I could find a lot of posts which said that calling dispose explicitly of the DirectorySearcher or ResultCollection object will solve the problem.

However, I see that the memory used by the task is increasing constantly. There isnt much else going in the other part of the code. When i comment the function, the memory usage becomes stable.

Has anyone else faced the issue and found a solution?

PS: And there is no way out. I need to do the findall :(


回答1:


You aren't disposing everything if an exception is thrown: you need to use a try/finally block or the equivalent using statement, something like:

void RunThis()
{
    using (DirectoryEntry de = new DirectoryEntry())
    {
        de.Path = "LDAP://" + domainName;
        de.Username = username;
        de.Password = password;
        de.AuthenticationType = AuthenticationTypes.Secure;

        using (DirectorySearcher deSearch = new DirectorySearcher(de))
        {
            deSearch.SearchScope = SearchScope.Subtree;
            using (SearchResultCollection rescoll = deSearch.FindAll())
            {
            }
        }
    }

} // end of function 



回答2:


The solution is here

Memory Leak when using DirectorySearcher.FindAll()

Some problem with the FindAll API implementation. If you dont enumerate the results and not use it once, then dispose wont work properly. However, after enumerating it and a simple enumerator.moveNext() done once, it disposes nice and clean. This has solved my problem.! :)




回答3:


First, you need to figure out whether it is managed or unmanaged memory that is leaking.

  1. Use perfmon to see what happens to your process '.net memory# Bytes in all Heaps' and Process\Private Bytes. Compare the numbers and the memory rises. If the rise in Private bytes outpaces the rise in heap memory, then it's unmanaged memory growth.

  2. Unmanaged memory growth would point to objects that are not being disposed (but eventually collected when their finalizer executes).

  3. If it's managed memory growth, then we'll need to see which generation/LOH (there are also performance counters for each generation of heap bytes).

  4. If it's Large Object Heap bytes, you'll want to reconsider the use and throwing away of large byte arrays. Perhaps the byte arrays can be re-used instead of discarded. Also, consider allocating large byte arrays that are powers of 2. This way, when disposed, you'll leave a large "hole" in the large object heap that can be filled by another object of the same size.

  5. A final concern is pinned memory, but I don't have any advice for you on this because I haven't ever messed with it.




回答4:


DirectoryEntry and DirectorySearcher both implement IDisposable. Also, you need to insure that they are disposed even in the event of an exception. I would suggest placing the construction of both inside using blocks.

EDIT: As does SearchResultCollection, so +1 to @Joe.




回答5:


Try using a using statement instead

void RunThis()
{
        using(DirectoryEntry de = new DirectoryEntry())
        {
          de.Path = "LDAP://" + domainName;
          de.Username = username;
          de.Password = password;
          de.AuthenticationType = AuthenticationTypes.Secure;

          DirectorySearcher deSearch = new DirectorySearcher(de);
          //Skipping properties to load
          try
          {
            deSearch.SearchScope = SearchScope.Subtree;
            SearchResultCollection rescoll = deSearch.FindAll();
            deSearch.Dispose();
            rescoll.Dispose();
          }
          catch (Exception obj)
          {
            System.Console.WriteLine("Exception in getting results. {0}",obj.Message);
          }
        }
}

This will not only dispose of the DirectoryEntry but will also clean up everything else in the using block for you.



来源:https://stackoverflow.com/questions/6362341/dispose-not-working-as-expected-in-directorysearcher

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!