簡體   English   中英

處置DirectorySearcher中的異常

[英]Dispose not working as expected in DirectorySearcher

我正在嘗試連接並執行簡單的功能,例如使用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 :(

如果拋出異常,則不會處理所有事情:您需要使用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 

解決方案在這里

使用DirectorySearcher.FindAll()時的內存泄漏

FindAll API實現存在一些問題。 如果您不枚舉結果而不使用一次,那么處理將無法正常進行。 但是,在枚舉它並完成一次簡單的enumerator.moveNext()之后,它會干凈利落地放置。 這解決了我的問題。 :)

首先,您需要確定泄漏的是托管內存還是非托管內存。

  1. 使用perfmon查看進程“ .net內存中所有堆中的字節數”和Process \\ Private字節如何處理。 比較數字,內存增加。 如果“專用字節”的增加超過了堆內存的增加,則是非托管內存的增加。

  2. 非托管內存的增長將指向未處置的對象(但最終執行它們的終結器時最終會收集它們)。

  3. 如果是托管內存增長,那么我們將需要查看哪一代/ LOH(每一代堆字節也有性能計數器)。

  4. 如果是大對象堆字節,則需要重新考慮大字節數組的使用和丟棄。 也許字節數組可以重用而不是丟棄。 另外,請考慮分配2的冪的大字節數組。這樣,在處理時,您將在大對象堆中留下一個大的“空洞”,該堆可由相同大小的另一個對象填充。

  5. 最后一個問題是固定的內存,但是對此我沒有任何建議,因為我從來沒有弄過它。

DirectoryEntry和DirectorySearcher都實現IDisposable 此外,即使在發生異常的情況下,也需要確保將它們丟棄。 我建議將兩個結構都放在使用block的內部。

編輯:和SearchResultCollection一樣,所以+1到@Joe。

嘗試改用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塊中的其他所有內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM