我正在尝试连接并执行简单的功能,例如使用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 :(答案 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)
首先,您需要弄清楚它是否是泄漏的托管或非托管内存。
使用perfmon查看您的进程会发生什么情况。所有堆中的字节数和字节数以及进程\专用字节数。比较数字和内存上升。如果Private字节的增长超过堆内存的增长,那么它就是非托管内存增长。
非托管内存增长会指向未被处置的对象(但最终会在终结器执行时收集)。
如果管理内存增长,那么我们需要查看哪一代/ LOH(每一代堆字节都有性能计数器)。
如果是大对象堆字节,则需要重新考虑使用和丢弃大字节数组。也许字节数组可以重复使用而不是丢弃。另外,考虑分配2的幂的大字节数组。这样,在处理时,你将在大对象堆中留下一个大的“洞”,可以被另一个相同大小的对象填充。
< / LI>最后一个问题是寄托记忆,但我对此没有任何建议,因为我从来没有搞过它。
答案 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
区块中的所有其他内容。