c++dllとの通信に使用されるアンマネージメモリ構造がいくつかあります。このような各構造は手動で解放する必要があるため、MyUnmanagedStructure
を実装するaでラップしますIDisposable
。
私は常にこれらの構造の可変数を一緒に必要とするので、MyUnmanagedStructureCollection
IDisposableも実装するコレクションがあります。
(最小限のサンプルコードについては、以下を参照してください)
私のライブラリのユーザーが常にDispose()を呼び出すか、コレクションをラップする限りusing() {}
問題はありませんが、それを保証することはできません。ユーザーがコレクションを手動で破棄しなくても、メモリをリークしたくありません。
代わりにファイナライザーを介してガベージコレクションによってメソッドが呼び出された場合、MyUnmanagedStructureCollection.Dispose()
私が理解している限り、自分private List<MyUnmanagedStructure>
がまだガベージコレクションされていないことを確認できません。その場合、各構造をどのように破棄できますか?
ファイナライズコードで、リストがまだガベージコレクションされていないことを期待して、リストを反復処理する必要がありますか?
これをtry/catchブロックで実行して、ObjectDisposedExceptionをキャッチすることをお勧めしますか?
または、個々のファイナライザーに依存して、各unmanagedStructureを「それ自体を守る」ようにし、コレクションのファイナライザーで何もしないようにする必要がありますか?
public class MyUnmanagedStructureCollection : IDisposable
{
private List<MyUnmanagedStructure> structures;
private bool disposed = false;
#region standard IDIsposable pattern
public ~MyUnmanagedStructureCollection()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
// Dispose unmanaged resources
// Should not access managed resources,
// the garbage collection may have claimed them already!
// PROBLEM!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// this.structures is a List<MyUnmanagedStructure>; so is a managed resource!!!
foreach (var structure in this.structures)
structure.Dispose(disposing)
this.removeAllMemoryPressure();
if (disposing)
{
// Dispose managed resources.
this.structures.Clear();
this.structures = null;
}
}
disposed = true;
}
}
public class MyUnmanagedBuffer : IDisposable
{
...
}