2009-07-08 96 views
2

我有我正在使用的第三方組件,我看到資源沒有被釋放的一些問題。該組件會導致Windows創建UDP套接字句柄(「\ Device \ Udp」以及「\ Device \ Afd」)。如果我允許程序執行和取消引用第三方對象,我認爲像過去一直使用的所有.NET對象一樣,對象將被垃圾收集。但是,Process Explorer顯示「\ Device \ Udp」句柄被無限期保留,直到實際進程被終止(或者在應用程序池的情況下被回收:對象沒有垃圾收集

此外,如果我手動調用這個對象的Dispose()方法,然後釋放這些句柄,這是我已經做好的修復,但我只是好奇它爲什麼需要這樣做。是否有可能組件的構建者已經做了某些事情或設置了有些屬性可以防止垃圾收集器調用破壞對象?

如果有幫助,我發佈了下面的代碼。代碼在Forms應用程序中使用,所以過程不會在while循環完成後結束。

不起作用

代碼(無限期地創建了100個手柄),做工作(制訂和發佈了手柄)

 for (int i = 0; i < n; i++) 
     { 
      Snmpmgr mgr = new Snmpmgr(); 
      mgr.Timeout = 10; 

      mgr.ObjCount = 1; 
      mgr.ObjId[1] = ".1.3.6.1.2.1.1.1.0"; 

      try 
      { 
       mgr.SendGetRequest(); // Handle shows up in ProcExplorer after this call 
      } 
      catch (Exception ex) 
      { 
       throw new TimeoutException("Error contacting CMTS."); 
      } 
     } // end of for... obj referenced by mgr never garbage collected 

代碼:

 for (int i = 0; i < n; i++) 
     { 
      Snmpmgr mgr = new Snmpmgr(); 
      mgr.Timeout = 10; 

      mgr.ObjCount = 1; 
      mgr.ObjId[1] = ".1.3.6.1.2.1.1.1.0"; 

      try 
      { 
       mgr.SendGetRequest(); // Handle shows up in ProcExplorer after this 
      } 
      catch (Exception ex) 
      { 
       throw new TimeoutException("Error contacting CMTS."); 
      } 
      mgr.Dispose(); // UDP Socket Handle freed... not sure that's how to spell free + ed :) 
     } 

在此先感謝您的幫助。

Chris

+0

你真的可以顯示一個代碼片段,說明你如何在Snmpmgr類中創建套接字句柄嗎? – jerryjvl 2009-07-08 02:27:19

+0

Snmpmgr是由nsoftware製作的第三方組件:http://www.nsoftware.com/portal/dotnet/。對於我們支付的價格標籤,我真的不想排除第三方軟件的故障。我主要是好奇的,如果他們的組織網絡的行爲可能有問題,那麼我可以開個案。 – regex 2009-07-08 06:15:48

回答

5

您在第二個示例中使用了mgr.Dispose調用。我會採取它mgr是一個IDisposable?

在這種情況下,你需要使用一個使用塊:

for (int i = 0; i < n; i++) 
{ 
    using(Snmpmgr mgr = new Snmpmgr()) 
    { 
     // Your Code 
    } 
} 
2

調用Dispose是做正確的事。有些對象使用非託管資源(如果您使用套接字,則可能是這種情況)。 Dispose方法被精確地公開,以便對象可以正確釋放其非託管資源。任何時候你使用一個實現IDisposable的對象,當你完成它時,你應該調用Dispose。

有關IDisposable的更詳細:How to dispose a class in .net?

2

這是關於Dipose()方法的點。由於不能知道何時會調用析構函數,因此應該使用Dispose釋放非託管資源。正如MiffTheFox所說,你應該把你的代碼放入一個「使用」塊中。當代碼執行到達「使用」塊的末尾時,Dipose()將自動調用。

1

也許你可以把mgr.Dispose()放在try/catch塊之後的「finally」子句中。

0

確實實際上在Snmpmgr類上實現了析構函數來釋放套接字句柄,對吧?否則GC不知道如果你沒有明確地通過Dispose()來完成釋放資源的工作。