我也有一个使用插件和应用程序域的长时间运行的服务,并且由于使用directoryservices而导致内存泄漏。请注意,我使用的是system.directoryservices.accountmanagement,但据我所知,它使用相同的底层ADSI API,因此容易发生相同的内存泄漏。
我查看了所有的CLR内存计数器,内存没有泄漏,并且在强制GC或卸载appdomain时都会返回。泄漏是在不断增长的私有字节中。我在这里搜索,在使用ADSI API时发现了一些与内存泄漏相关的问题,但它们似乎表明,只需在目录搜索器上迭代就可以解决问题。但正如您在下面的代码中看到的,我在foreach块中执行此操作,但内存仍在泄漏。有什么建议吗?下面是我的方法:
public override void JustGronkIT()
{
using (log4net.ThreadContext.Stacks["NDC"].Push(GetMyMethodName()))
{
Log.Info("Inside " + GetMyMethodName() + " Method.");
System.Configuration.AppSettingsReader reader = new System.Configuration.AppSettingsReader();
//PrincipalContext AD = null;
using (PrincipalContext AD = new PrincipalContext(ContextType.Domain, (string)reader.GetValue("Domain", typeof(string))))
{
UserPrincipal u = new UserPrincipal(AD);
u.Enabled = true;
//u.Surname = "ju*";
using (PrincipalSearcher ps = new PrincipalSearcher(u))
{
myADUsers = new ADDataSet();
myADUsers.ADUsers.MinimumCapacity = 60000;
myADUsers.ADUsers.CaseSensitive = false;
foreach (UserPrincipal result in ps.FindAll())
{
myADUsers.ADUsers.AddADUsersRow(result.SamAccountName, result.GivenName, result.MiddleName, result.Surname, result.EmailAddress, result.VoiceTelephoneNumber,
result.UserPrincipalName, result.DistinguishedName, result.Description);
}
ps.Dispose();
}
Log.Info("Number of users: " + myADUsers.ADUsers.Count);
AD.Dispose();
u.Dispose();
}//using AD
}//Using log4net
}//JustGronkIT我对foreach循环做了以下更改,它更好,但私有字节仍然会增长,并且永远不会被回收。
foreach (UserPrincipal result in ps.FindAll())
{
using (result)
{
try
{
myADUsers.ADUsers.AddADUsersRow(result.SamAccountName, result.GivenName, result.MiddleName, result.Surname, result.EmailAddress, result.VoiceTelephoneNumber, result.UserPrincipalName, result.DistinguishedName, result.Description);
result.Dispose();
}
catch
{
result.Dispose();
}
}
}//foreach发布于 2012-06-29 22:06:08
我说得太快了,仅仅是激进地调用Dispose()并不能从长远来看解决问题。真正的解决方案是什么?停止同时使用directoryservices和directoryservices.accountmanagement,改为使用directoryservices,并对我的域进行分页搜索,因为微软方面没有泄漏该程序集。
按照要求,这里有一些代码来说明我提出的解决方案。请注意,我还使用了插件架构和appdomain,当我使用完appdomain时,我会卸载它,尽管我认为如果DirectoryServices.Protocols中没有泄漏,您不必这样做。我之所以这样做,只是因为我认为使用appDomains可以解决我的问题,但由于这不是托管代码中的泄漏,而是非托管代码中的泄漏,所以它没有任何好处。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.Protocols;
using System.Data.SqlClient;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Text.RegularExpressions;
using log4net;
using log4net.Config;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
namespace ADImportPlugIn {
public class ADImport : PlugIn
{
private ADDataSet myADUsers = null;
LdapConnection _LDAP = null;
MDBDataContext mdb = null;
private Orgs myOrgs = null;
public override void JustGronkIT()
{
string filter = "(&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))";
string tartgetOU = @"yourdomain.com";
string[] attrs = {"sAMAccountName","givenName","sn","initials","description","userPrincipalName","distinguishedName",
"extentionAttribute6","departmentNumber","wwwHomePage","manager","extensionName", "mail","telephoneNumber"};
using (_LDAP = new LdapConnection(Properties.Settings.Default.Domain))
{
myADUsers = new ADDataSet();
myADUsers.ADUsers.MinimumCapacity = 60000;
myADUsers.ADUsers.CaseSensitive = false;
try
{
SearchRequest request = new SearchRequest(tartgetOU, filter, System.DirectoryServices.Protocols.SearchScope.Subtree, attrs);
PageResultRequestControl pageRequest = new PageResultRequestControl(5000);
request.Controls.Add(pageRequest);
SearchOptionsControl searchOptions = new SearchOptionsControl(System.DirectoryServices.Protocols.SearchOption.DomainScope);
request.Controls.Add(searchOptions);
while (true)
{
SearchResponse searchResponse = (SearchResponse)_LDAP.SendRequest(request);
PageResultResponseControl pageResponse = (PageResultResponseControl)searchResponse.Controls[0];
foreach (SearchResultEntry entry in searchResponse.Entries)
{
string _myUserid="";
string _myUPN="";
SearchResultAttributeCollection attributes = entry.Attributes;
foreach (DirectoryAttribute attribute in attributes.Values)
{
if (attribute.Name.Equals("sAMAccountName"))
{
_myUserid = (string)attribute[0] ?? "";
_myUserid.Trim();
}
if (attribute.Name.Equals("userPrincipalName"))
{
_myUPN = (string)attribute[0] ?? "";
_myUPN.Trim();
}
//etc with each datum you return from AD
}//foreach DirectoryAttribute
//do something with all the above info, I put it into a dataset
}//foreach SearchResultEntry
if (pageResponse.Cookie.Length == 0)//check and see if there are more pages
break; //There are no more pages
pageRequest.Cookie = pageResponse.Cookie;
}//while loop
}//try
catch{}
}//using _LDAP
}//JustGronkIT method
}//ADImport class
} //namespace发布于 2014-08-07 21:25:07
我遇到了一个很大的内存泄漏,因为像你一样,我写了这样的东西...
foreach (GroupPrincipal result in searcher.FindAll())
{
results.Add(result.Name);
}但是诀窍是FindAll本身返回一个必须被释放的对象……
using (var searchResults = searcher.FindAll())
{
foreach (GroupPrincipal result in searchResults)
{
results.Add(result.Name);
}
}发布于 2012-06-14 23:27:42
我相当确定这是一个已知的错误( http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/6a09b8ff-2687-40aa-a278-e76576c458e0 )。
解决方法?使用DirectoryServices库...
https://stackoverflow.com/questions/11034265
复制相似问题