2009-07-08 4 views
2

私は使用しているサードパーティのコンポーネントを持っていますが、リソースが解放されていないという問題があります。このコンポーネントは、ウィンドウに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

+0

Snmpmgrは、nsoftwareが作成した第三者コンポーネントです(http://www.nsoftware.com/portal/dotnet/)。私たちが支払う価格表のために、私は実際にサードパーティのソフトウェアのトラブルシューティングのような気がしません。私は主に、彼らのcomponentsenetの動作に何らかの問題があったかどうか不思議でしたので、私は事件を開くことができました。 – regex

+0

以下に述べるように、正しい答えは、オブジェクトの処理が完了したときにオブジェクトをDispose()することです。つまり、ベンダーが廃棄パターンを適切に実装していないように思えます(http://msdn.microsoft.com/en-us/library/fs2xkftw%28VS.80%29.aspxおよびhttp://stackoverflow.com参照)。/questions/898828/c-finalize-dispose-pattern)。要するに、管理対象外のリソースを処分する必要があるクラスがある場合、Dispose()がまだ確定的に呼び出されていない場合は、ガベージコレクション中に自分自身で処分する必要があります。 –

答えて

5

2番目の例では、mgr.Disposeコールを使用しました。私はそれを取るだろうmgrはIDisposableですか?その場合

は、あなたが使用してブロックを使用する必要があります。廃棄を呼び出す

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

良い提案。 Dispose()の呼び出しが私のコードではなくコンパイラを介して作成されている点を除いて、私は上記のコードと同じであるusingステートメントを覚えていませんでしたか?私の擬似コードを最適化するため+1。しかし、私のプロダクション環境では、SnmpmgrはPageクラスのグローバル変数です(ボタンクリックイベントとロードイベントで複数回使用されるため)。したがって、使用後に直接Disposeするオプションはありません私は15の異なる機会にオブジェクトを再現したい)。申し訳ありませんが、私は元の投稿でそれを言及しませんでした。 – regex

+1

*必要ではないブロックを使用する*。それはおそらく良い考えですが、それは必要ではありません。 Disposeを呼び出すと、同じことが達成されますが、Disposeの呼び出しはおそらくfinallyブロック内にあるはずです。 –

+3

使用するたびにオブジェクトを破棄したくない場合は、ある時点で破棄されるようにする必要があります。あなたがこれを行うことができる信頼できるポイントがあれば、それはうまくいくでしょう。しかし、一般的には、そうすることが理にかなったらすぐに処分することをお勧めします。だから、あなたが望むよりも長くオブジェクトを保持していないことを確認してください。これについて慎重に考える。 –

2

は行うには適切なものです。いくつかのオブジェクトは管理されていないリソースを使用します(ソケットを使用している場合はそうかもしれません)。 Disposeメソッドは、オブジェクトがアンマネージリソースを適切に解放できるように、正確に公開されます。 IDisposableを実装するオブジェクトを使用するときはいつでも、終了したらDisposeを呼び出す必要があります。

IDisposableをについての詳細については

:破棄して下さい()メソッドについてのポイントだHow to dispose a class in .net?

2

。デストラクタを呼び出すタイミングを決して知らないので、Disposeを使用してアンマネージリソースを解放する必要があります。 MiffTheFoxは言ったように、あなたのコードを 'using'ブロックの中に置くべきです。コードの実行が 'using'ブロックの最後に達すると、Dipose()が自動的に呼び出されます。

1

おそらく、try/catchブロックの後に、 "finally"節にmgr.Dispose()を入れることができます。

0

実際にはSnmpmgrクラスのデストラクタを実装してソケットハンドルを解放するのですか? ...そうでなければ、GCは、Dispose()で明示的に行うのではなく、リソースを解放するために何らかの作業があることを知りません。

関連する問題