Утилизация не работает должным образом в DirectorySearcher - PullRequest
2 голосов
/ 15 июня 2011

Я пытаюсь подключиться и выполнить простые функции, такие как поиск в Active Directory с использованием C #.Тем не менее, я застрял в проблеме.Я использую 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 

Это примерная функция, до которой я урезан.Я мог найти много сообщений, в которых говорилось, что вызов dispose явно объекта DirectorySearcher или ResultCollection решит проблему.

Однако я вижу, что память, используемая задачей, постоянно увеличивается.В остальной части кода больше ничего не происходит.Когда я комментирую функцию, использование памяти становится стабильным.

Кто-нибудь еще сталкивался с проблемой и нашел решение?

PS: И выхода нет.Мне нужно найти все: (

Ответы [ 5 ]

3 голосов
/ 17 июня 2011

Решение здесь

Утечка памяти при использовании DirectorySearcher.FindAll ()

Некоторая проблема с реализацией API FindAll.Если вы не перечислите результаты и не используете его один раз, тогда утилизация не будет работать должным образом.Однако после его перечисления и простого выполнения enumerator.moveNext (), выполняемого один раз, он удаляется и становится чистым.Это решило мою проблему.:)

3 голосов
/ 15 июня 2011

Вы не утилизируете все, если выдается исключение: вам нужно использовать блок 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 голос
/ 16 июня 2011

Во-первых, вам необходимо выяснить, протекает ли управляемая или неуправляемая память.

  1. Используйте perfmon, чтобы увидеть, что происходит с вашим процессом .net memory # Байт во всехКучи и процесс \ Частные байты.Сравните цифры и память возрастет.Если увеличение количества приватных байтов опережает увеличение объема динамической памяти, это означает рост неуправляемой памяти.

  2. Рост неуправляемой памяти будет указывать на объекты, которые не удаляются (но в конечном итоге собираются при их финализации).выполняется).

  3. Если это управляемый рост памяти, то нам нужно посмотреть, какое поколение / LOH (есть также счетчики производительности для каждого поколения байтов кучи).

  4. Если это байты кучи больших объектов, вам нужно пересмотреть использование и отбрасывание больших байтовых массивов.Возможно, байтовые массивы можно использовать повторно, а не отбрасывать.Кроме того, рассмотрите возможность выделения больших байтовых массивов со степенями 2. Таким образом, при удалении вы оставите большую «дыру» в куче больших объектов, которая может быть заполнена другим объектом того же размера.

  5. Последнее беспокойство связано с памятью, но у меня нет для вас никаких советов по этому поводу, потому что я никогда с ней не связывался.

0 голосов
/ 15 июня 2011

Попробуйте вместо этого использовать оператор 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.

0 голосов
/ 15 июня 2011

DirectoryEntry и DirectorySearcher реализуют IDisposable .Также вам необходимо убедиться, что они утилизируются даже в случае исключения.Я бы предложил разместить конструкцию обоих внутри , используя блоки .

РЕДАКТИРОВАТЬ: Как и SearchResultCollection, так что от +1 до @ Джо.

...