5

ファイナライザとデストラクタが実装された「CTransferManaged」という名前の C++/CLI クラスがあります。

CTransferManaged::~CTransferManaged()
{
    this->!CTransferManaged();
}
CTransferManaged::!CTransferManaged()
{
    //Clean up resources... 
}

このクラスは、タイプ CTransferManaged のオブジェクト m_transfer を含む「CTransfer」という名前の C# クラスでラップされます。

このクラスのデストラクタがオブジェクト m_transfer への参照のみをクリアする場合、デストラクタが呼び出される (ブレークポイントがヒットする) ことがわかります。

~CTransfer()
{
    m_transfer = null; //breakpoint on this line
}

他に何も変更せずに m_transfer オブジェクトの Dispose() 関数を呼び出すと、デストラクタは呼び出されなくなります (ブレークポイントはヒットしなくなります)。なぜだと思いますか?

~CTransfer()
{
    m_transfer.Dispose(); //breakpoint on this line
    m_transfer = null;
}

Dispose() を手動で呼び出さないと、C++/CLI オブジェクト (m_transfer) のリソースが適切にクリーンアップされないことがわかったので、手動で Dispose() を呼び出したいと思います。現時点では、正確な理由はわかりません。

CTransferManaged::Dispose() (C++/CLI) を呼び出すとすぐに、CTransfer (C# クラス) のデストラクタが呼び出されなくなったのはなぜですか?

4

2 に答える 2

0

Disposing と Finalizing の典型的なパターンは、Dispose を呼び出すときに、ファイナライザーを抑制する必要があるというものです。Dispose は、実行されるとすぐにリソースをクリアすることを目的としていますが、ファイナライザーは、ガベージ コレクターがクラスを収集するたびにリソースをクリアすることを目的としています...どちらも同じことを行うこと (アンマネージ リソースを解放すること) を目的としているため、 Dispose、ファイナライザーの呼び出しは冗長で不要になり、オブジェクトが収集されて破棄される前に最初に Finalizer キューに配置されるため、オブジェクトが必要以上に長く存続する原因にもなります。これにより、多くのオブジェクトを作成および破棄する、頻繁にアクセスされるアプリケーションでメモリ管理が不十分になります。したがって、C# のほとんどの Dispose メソッドは次を呼び出します。

GC.SuppressFinalize(this);

これは、ガベージ コレクターにファイナライザーを実行しないように指示します。このパターンは広く使用されており、アンマネージ クラスでも使用される可能性があります。これがおそらく、Dispose 呼び出しでデストラクタが削除される理由です。

于 2013-06-06T15:49:30.300 に答える