0

最近Microsoft.VisualBasic.FileIO.TextFieldParser、テキスト入力を解析する方法を学びました。私に与えられた例でTextFieldParserは、キーワードを使用して呼び出されますusing

using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(new StringReader(str)))

さらに調査 結果、キーワード forを使用する慣行は普遍的ではないことに気付きました。 usingTextFieldParser

私の知る限り、.NetFramework にはマネージド リソースとアンマネージド リソースの両方があります。また、アンマネージ リソースを使用する場合は、メモリ リークを心配する必要があるため、使用するアンマネージ リソースの破棄に注意する必要があります。usingこれを行うための最善の方法の 1 つは、それらをコンテキストに置くことです。

これらすべてのことから、私は頭の中に 2 つの疑問を抱くようになりました。ここに私の質問があります:

  1. 特定: TextFieldParser は実際に管理されているか管理されていないか?
  2. 一般:リソースが管理されているか管理されていないかを知るための明確なX方法はありますか (クラス内のものを見るなど、またはMSDNから何かを確認するなど)。(i) ほとんどの.Netクラスが管理されている、(ii) System.Drawing クラスには管理されていないリソースがいくつかある、(iii) すべてのデータベース、ネットワーク、および COM クラスに注意してください。通常、管理されていないなど...そして、私が今まで追加し続けているリストが続きます. しかし、これを知る明確な方法があるのだろうか?

より経験豊富な方が、この問題についてさらに私を導くのに役立つことができれば、本当に感謝しています.

4

2 に答える 2

3

あなたは要点を逃しています。クラスが を実装するときはいつでもIDisposable、使い終わったら呼び出す必要がありDisposeます。

クラスがアンマネージ リソースを使用するかどうかは、クラスの内部的なものであるため、まったく気にする必要はありません。アンマネージ リソースを使用するすべてのクラスには、クラスを明示的に破棄しなかった場合にそれらのアンマネージ リソースをクリアするファイナライザーも必要です。Disposeより決定論的かつ即時の方法で、そのリソースをクリーンアップできるようにするだけです (マネージドとアンマネージドの両方。ただし、これは必ずしもメモリをすぐに解放することを意味するわけではありません)。たとえば、DisposeaFileStreamを実行するとファイル ハンドルがすぐに解放されますが、実行しない場合Dispose(またはClose)、ファイルは次の収集とファイナライズまで開かれます。

編集:

Dispose管理対象リソースをクリーンアップするためにも必要である可能性があることを示すために、イベント ハンドラーのみを確認する必要があります。特に、自分よりも寿命が長いクラスのイベントを購読している場合:

var control = new MyHelperControl();
MyParentForm.Click += control.DoSomething();

これで、スコープ外になったとしても、イベント ハンドラーによって参照されているcontrol限り存続します。MyParentForm親の寿命がアプリケーション全体と同じである場合、同じ問題がばかげた比率に発展します。これは、巨大なメモリ リークになる可能性があります。例としては、アプリケーションのメイン フォームまたは静的イベントにイベント ハンドラーを登録することがあります。

で起こる他のこともあるかもしれませんDispose。たとえば、再び Windows フォームで を呼び出すDisposeと、Controlさまざまなことが起こります。

  • アンマネージ リソースはすべて解放されます。Winforms コントロールはある程度ネイティブ コントロールのラッパーであるため、これは通常、多くのリソース (コントロール自体、ペン、ブラシ、画像など) です。これらはすべてネイティブ リソースです。それらはすべてファイナライザーを持っているため、 a を忘れた場合にも解放されますがDispose、より多くの時間がかかる可能性があります。これは、これらのオブジェクトを多数作成および破棄する場合に特に苦痛です。たとえば、GDI+ オブジェクト ハンドルの供給には限りがあり、使い切れば手に負えなくOutOfMemoryExceptionなります。
  • すべてのサブコントロールを破棄します。
  • コンテキスト メニュー ハンドラーをすべて削除します (コンテキスト メニューは、別のコントロールにのみリンクされている別のコンポーネントであることを思い出してください)。
  • データ バインディングをすべて削除します。
  • 親コンテナがあれば、そこから自身を削除します。
  • コントロールが独自のメッセージ ループを持つウィンドウである場合は、メッセージ ループを強制終了します。

面白いのは、管理されていないリソースが最も重要でないということです。実際には、常にファイナライザーがあります。ファイナライザーで管理された参照を処理することは多かれ少なかれ禁止されているため、管理されたリソースはよりトリッキーです (既に解放されているか、解放されている最中であるか、途中で解放され始める可能性があるため)ファイナライザーの...複雑です)。そのため、ファイナライザーでこれを行うMyParentForm.Click -= this.OnClick;のは良いことではありません。言うまでもなく、そのようなすべてのクラスをファイナライズ可能にする必要があります。これは、特にファイナライザーが実際に実行されることを期待する場合( Dispose. GC は、このインスタンスがファイナライズを必要としなくなったことを警告されます)。

于 2016-01-05T10:02:32.410 に答える
1

IDisposable インターフェイスを実装するクラスの使用は、using (...) {} でラップするか、適切な場所で適切に破棄する必要があります。

于 2016-01-05T10:02:11.447 に答える