3

アンマネージ メモリへのポインターを受け取るアンマネージ関数を使用しています。この関数は呼び出されるとすぐに戻り、バックグラウンドでメモリ上で非同期に動作します。操作が完了すると、追加の IntPtr がマネージ コードに返されます。このような操作を複数同時に実行することができます。

非同期操作が完了したときに取得したいカスタム SafeBuffer インスタンスにアンマネージ メモリへのポインターをカプセル化しています。SafeBuffer は、メモリへの参照がない場合に、メモリが適切に解放されることを保証します。問題は、メモリがまだアンマネージ関数によって使用されている間は、メモリを解放してはならないということです。

どうすればこれを達成できますか?アンマネージ関数は何十億回も呼び出されるため、パフォーマンスが重要です。

関数を呼び出すたびに GCHandle を割り当て、それを使用して操作が完了したときに SafeBuffer を取得し、それを解放することができます。ただし、ハンドルの割り当てにはコストがかかるようで、時間の経過とともにパフォーマンスが大幅に低下します。

GCHandle を 1 回割り当てることはできますが、メモリがアンマネージ関数によって使用されておらず、SafeBuffer への参照がない場合、アンマネージ メモリは解放されません。

何か案は?

4

2 に答える 2

0

管理対象側にルックアップ テーブルを保持できます。

static ConcurrentDictionary<long, SafeBuffer> handles = new ...();
static long nextHandle = 0;

static long GetNextHandle(SafeBuffer buffer) {
    var handle = Interlocked.Increment(ref nextHandle);
    handles.Add(handle, buffer);
    return handle;
}

GetNextHandleアンマネージ コードを呼び出す前に呼び出します。完了したら、handlesディクショナリからハンドルを削除します。

ハンドルは、long安定した (変更されない) 任意のものであり、アンマネージ コードに渡すことができます。

于 2013-07-17T19:40:33.763 に答える