2009-04-23 4 views
1

ネットからビットマップに直接ストリーミングして画像を読み込んでいたのを覚えています。ストリームを閉じ、ビットマップを返し、イメージコントロールに保持します。GCとIDisposeはどのようにC#で動作しますか?

私がloadPicture()を実行したときを除いて、スマートポインタがC++で行うように、最初のビットマップは解放されます。しかし、それは私が処分と呼ぶまで、私は多くのラムを消費しなかった。だから私の質問です。

GCおよびDispose可能オブジェクトは、どのようにC#で動作しますか?なぜsmart_ptrのように実装されていないのですか?

答えて

2

ランタイムが必要と感じるときにGCが起動します。

基本的なルールは、使い捨てタイプ(IDispose)を使用する場合は、使用する必要がなくなったときにDisposeを呼び出すことによって、プログラマとして、そのタイプで使用されるリソースをできるだけ早く解放する必要があります。そのタイプ。 たとえば、ファイルを読むときには、読み込んだ直後にファイルを閉じます。 (closeを呼び出すと、この場合はdisposeも呼び出されます)。

8

参考文献はスマートポインタではありません。スコープの外に出て、別の値に置き換えたり、nullで設定したりすることは、まったく同じです何もない。これは、単にCLI/GCの設計の一部である

...

Gargageコレクション(GC)を必要なときにを実行し、使用管理するメモリをクリーンアップする必要があり、かつ(ファイナライザが提供されている場合)管理されていないリソースもあります。しかし、確定的なクリーンアップの場合、それはIDisposableの目的全体です。 usingで処理するか、この責任を負っているもの(通常はストリーム/リーダなどで扱う)に渡すことは、Dispose()のオブジェクトです。

using (StreamReader reader = new StreamReader(myfile))) 
{ 
    ... 
} 
+0

+1です。私はこの質問が既に尋ねられていることを確かめてください:) –

+0

私は何も処分する必要はないと言っていますか? –

+0

あなたがしなくても、リソースは最終的に解放されます(つまり、IDisposableが正しく実装されている場合)。実際には、これは単なる安全ネットです。管理対象外のリソースをできるだけ早く解放する必要があります。 –

0

smart_ptrが参照カウントされます。これにより、コードによって参照されなくなった時点でリソースの確定的な解放が可能になりますが、参照の割り当ては常にカウンタの更新を必要とし、循環参照が自動的に解放されず、メモリリーク、メモリマネージャがより頻繁に呼び出されます。

.NETのGCは、掃引コレクタです。メモリが解放されるべきであると感じる(通常はメモリ使用状況によってトリガされるが、確定的ではない)と感じるときはいつでも開始され、システム内のすべてのライブ参照のリストを作成することから始まる(CPUレジスタ、ネストされた参照など)。これは、ポインタ演算などを行うことができない管理された環境にあるため動作します。システムはすべての参照を追跡できます。ライブ参照のリストが作成された後、基本的には使用されていないすべてのメモリが解放されます。もちろん、これはちょうど基本的なスケッチです。管理されていないリソースの効率と管理のために、オブジェクト世代、ファイナライザなどのようなものがありますが、その仕組みの基本的な理解には重要ではありません。

IDisposableインターフェイスは、使い捨てパターンを実装するために使用され、決定的な方法で配置する必要があるオブジェクトを扱うときに役立ちます。パターンは、オブジェクトがもはや必要なくなったときにDispose()が明示的に呼び出され、アンマネージ・リソースやクローズ・ハンドルなどを解放し、メモリーを解放しないようにするためのパターンです。これは後でGCによって行われますが、リソースの確定的リリースが既に実行されているため、後でこの問題が発生することはありません。

1

IDisposableを実装しているオブジェクトでは、明示的にDisposeを呼び出す必要があります。そうしないと、アンマネージドリソースは処分されません。明示的に呼びたくない場合は、Disposeメソッドを呼び出すためにFinalizeメソッドをオーバーライドする必要があります。そのため、頻繁にこれが表示されます。

class MyClass : IDisposable 
{ 
    ... 

    ~MyClass() 
    { 
     this.Dispose(false); 
    } 

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

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { /* dispose managed stuff also */ } 

     /* but dispose unmanaged stuff always */ 
    } 
} 
関連する問題