在DirectorySearcher中处理不按预期工作

时间:2011-06-15 18:14:37

标签: c# memory-leaks active-directory directoryservices

我正在尝试连接并执行简单的功能,例如使用C#在Active Directory上进行搜索。但是,我遇到了问题。我正在使用DirectorySearcher搜索目录。目录中有大量条目。

这是功能

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 

这是我修剪过的示例函数。我可以找到很多帖子,这些帖子表明明确调用DirectorySearcher或ResultCollection对象可以解决问题。

但是,我发现任务使用的内存不断增加。代码的其他部分还有很多其他内容。当我评论该功能时,内存使用率变得稳定。

还有其他人遇到过这个问题并找到了解决方案吗?

PS:而且没有出路。我需要做findall :(

5 个答案:

答案 0 :(得分:3)

如果抛出异常,则不会处置所有内容:您需要使用try / finally块或等效的using语句,如:

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 

答案 1 :(得分:3)

解决方案就在这里

Memory Leak when using DirectorySearcher.FindAll()

FindAll API实现存在一些问题。如果你没有枚举结果而不使用它,那么处理将无法正常工作。但是,在枚举它和简单的enumerator.moveNext()完成一次之后,它处理得很好而且干净。这解决了我的问题。 :)

答案 2 :(得分:1)

首先,您需要弄清楚它是否是泄漏的托管或非托管内存。

  1. 使用perfmon查看您的进程会发生什么情况。所有堆中的字节数和字节数以及进程\专用字节数。比较数字和内存上升。如果Private字节的增长超过堆内存的增长,那么它就是非托管内存增长。

  2. 非托管内存增长会指向未被处置的对象(但最终会在终结器执行时收集)。

  3. 如果管理内存增长,那么我们需要查看哪一代/ LOH(每一代堆字节都有性能计数器)。

  4. 如果是大对象堆字节,则需要重新考虑使用和丢弃大字节数组。也许字节数组可以重复使用而不是丢弃。另外,考虑分配2的幂的大字节数组。这样,在处理时,你将在大对象堆中留下一个大的“洞”,可以被另一个相同大小的对象填充。

    < / LI>
  5. 最后一个问题是寄托记忆,但我对此没有任何建议,因为我从来没有搞过它。

答案 3 :(得分:0)

DirectoryEntry和DirectorySearcher都实现了IDisposable。此外,您需要确保即使在例外的情况下也会处置它们。我建议将两者的结构放在using blocks内。

编辑:和SearchResultCollection一样,所以+1给@Joe。

答案 4 :(得分:0)

尝试使用using语句

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);
          }
        }
}

这不仅会处理DirectoryEntry,还会清除using区块中的所有其他内容。