11

C#で手動でクリーンアップする必要があるリソースは何ですか?そうしないとどうなりますか?

たとえば、次のコードがあるとします。

myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
// Use Brush

Dispose メソッドを使用してブラシをクリーンアップしない場合、ガベージ コレクターがプログラムの終了時に使用されたメモリを解放すると仮定していますか? これは正しいです?

手動でクリーンアップするには、他にどのようなリソースが必要ですか?

4

14 に答える 14

7
  • 内部ウィンドウ データ構造へのハンドル。
  • データベース接続。
  • ファイル ハンドル。
  • ネットワーク接続。
  • COM/OLE 参照。

リストは続きます。

呼び出すことが重要です。Disposeさらに良いことに、usingパターンを使用します。

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}

何かを破棄しない場合、ガベージ コレクターがそのオブジェクトへの参照がなくなったことに気付くと、そのオブジェクトはクリーンアップされます。

の場合、System.Drawing.Brushすべてのプログラムがハンドルを解放するまで、Windows はブラシの内部ウィンドウ構造をメモリにロードしたままにします。

于 2008-09-22T19:57:24.763 に答える
7

何かを破棄しない場合、ガベージ コレクターがコード内にそのオブジェクトへの参照がなくなったことに気付いたときにクリーンアップされます。これにはしばらく時間がかかる場合があります。そのような場合、それは実際には問題ではありませんが、開いているファイルの場合はおそらく問題になります。

一般に、何かに Dispose メソッドがある場合は、使い終わったときにそれを呼び出すか、可能であればusingステートメントでラップする必要があります。

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}
于 2008-09-22T19:59:11.700 に答える
3

IDisposableを破棄しない場合の結果は、パフォーマンスへの影響がごくわずかであることから、アプリがクラッシュすることまでさまざまです。

例のBrushオブジェクトは、GCによってクリーンアップされます。しかし、あなたのプログラムは、以前にそれをクリーンアップすることによって得たであろうその少しの余分なメモリの恩恵を受けていなかったでしょう。多数のBrushオブジェクトを使用している場合、これは重要になる可能性があります。GCは世代別のガベージコレクターであるため、オブジェクトがあまり長く存在しない場合は、オブジェクトのクリーンアップにも効率的です。

一方、データベース接続オブジェクトを破棄しないと、プールされたデータベース接続がすぐに不足し、アプリがクラッシュする可能性があります。

どちらかを使用

using (new DisposableThing...
{
    ...
}

または、オブジェクト内のIDisposableへの参照を存続させる必要がある場合は、オブジェクトにIDisposableを実装し、IDisposableのDisposeメソッドを呼び出します。

class MyClass : IDisposable
{
    private IDisposable disposableThing;

    public void DoStuffThatRequiresHavingAReferenceToDisposableThing() { ... }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    //etc... (see IDisposable on msdn)

}

于 2008-09-22T20:04:57.677 に答える
2

一般に、IDisposable を実装するものはすべて、使用しているリソースを一時停止して調査する必要があります。

GC はメモリ プレッシャーがある場合にのみ発生するため、いつ発生するかを予測することはできません。AppDomain のアンロードは確かにそれをトリガーしますが。

于 2008-09-22T19:57:27.260 に答える
1

特定のオブジェクトが使い捨てリソースであるかどうか思い出せないときに使用するトリックは、宣言の後に「.Dispose」と入力して (せいぜい!)、Intellisense にチェックさせることです。

MemoryStream ms = new MemoryStream().Dispose

次に、.Dispose を削除し、using() ディレクティブを使用します。

using(MemoryStream ms = new MemoryStream())
{
  ...
}
于 2008-09-22T21:05:52.947 に答える
1

技術的には、IDisposable から継承するものはすべて積極的に破棄する必要があります。'using' ステートメントを使用すると、作業が簡単になります。

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

ドキュメントのサンプル コードや、ツール (Visual Studio など) によって生成されたコードで、IDisposable 派生オブジェクトの使用に一貫性がない場合があります。

IDisposable の優れている点は、基になるアンマネージ リソースを事前に解放できることです。場合によっては、本当にこれが必要になることもあります。たとえば、ネットワーク接続やファイル リソースを考えてみてください。

于 2008-09-22T20:01:48.387 に答える
1

他の人が言ったように、使用はあなたの友達です。最も重要な部分を除外することで、エラーが発生しにくい、かなり単純な方法で IDisposable を実装する方法について、このブログ エントリを書きました。

于 2008-09-22T20:09:07.060 に答える
0

最初にプログラムが終了すると、プロセスによって使用されるメモリがプロセス自体で削除されると想定できます。

disposeまたはdestructorin.netを使用している間、GCによってdispose関数が呼び出される時間は非決定的であることを理解する必要があります。そのため、disposeを明示的に使用または呼び出すことをお勧めします。

ファイルなどのリソースを使用する場合は、セマフォなどのメモリオブジェクトや、.netのマネージドワールドの外部にあるリソースを解放する必要があります。

たとえば、SolidBrushはGDIオブジェクトであり、.netの世界の外に存在するため、破棄する必要があります。

于 2008-09-22T20:03:44.077 に答える
0

ガベージコレクタは、プログラムの終了時に解放されるだけでなく、それ以外の場合はあまり役に立ちません(適切な/最近のOSでは、プロセスが終了すると、とにかくすべてのメモリがOSによって自動的にクリーンアップされます)。

C / C ++と比較したC#の大きな利点の1つは、割り当てられたオブジェクトを解放することを気にする必要がないことです(少なくともほとんどの場合)。gcは、ランタイムが決定したときにそれを実行します(いつ/どのように実行するかについてのさまざまな戦略)。

多くのリソースはgcによって処理されません:ファイル、スレッド関連のリソース(ロック)、ネットワーク接続など...

于 2008-09-22T20:04:05.073 に答える
0

マネージ バージョンのリソースを使用し、自分で Windows API を呼び出さない限り、問題はありません。「ウィンドウハンドル」(およびその他の多くのもの)はオブジェクトではなく.NETで知られているため、取得したものがIntPtrである場合にリソースを削除/破棄する必要があることだけを心配してください。

ところで、リソース (他の .NET オブジェクトと同様) は、現在のコンテキストを離れるとすぐにコレクションのフラグが立てられるため、メソッド内でブラシを作成すると、メソッドを終了するときにフラグが立てられます。

于 2008-09-22T19:59:10.890 に答える
0

管理されている場合 (つまり、フレームワークの一部)、心配する必要はありません。IDisposable を実装する場合は、usingブロックでラップするだけです。

管理されていないリソースを使用する場合は、ファイナライザーを読み、IDisposable を自分で実装する必要があります。

この質問の下にさらに多くの詳細があります

于 2008-09-22T20:00:18.920 に答える
0

注意すべき点の 1 つは、GC には小さく見えるがそうではないオブジェクトです。 GCが知らない大量のメモリ(私が信じているヒープ内)を実際につかみました。たとえば、これらのすべての束を foreach している場合、いくつかの楽しいメモリの問題に遭遇します。常に using または dispose を使用することを忘れないでください!

于 2008-09-22T20:08:40.727 に答える
0

オブジェクトを、解放する必要のあるリソースを「保持している」と考えるよりも、オブジェクトが何かを変更した (おそらくコンピュータの外部で!) と考えるほうがよいでしょう。元に戻すことも「クリーンアップ」することもできませんが、オブジェクトのみがクリーンアップできます。この変更は通常、プール内の具体的なオブジェクトが「ビジー」とマークされるという形を取りますが、その正確な形は問題ではありません。重要なのは、変更を元に戻す必要があり、そのために必要な情報がオブジェクトに保持されていることです。

于 2010-12-01T23:10:38.590 に答える
-3

ガベージ コレクターは、すべての管理対象リソースを処理します。あなたの例では、ガベージコレクターが決定したときにブラシがクリーンアップされます。これは、ブラシへの最後の参照が無効になった後に発生します。

手動でクリーンアップする必要がある特定のものがありますが、それらは DLL 呼び出しなどのアンマネージ ソースから取得されたポインターであり、.NET Framework 内では何もこの処理を必要としません。

于 2008-09-22T19:58:40.033 に答える