我正在使用一个非托管函数,该函数采用指向某个非托管内存的指针。该函数在调用时立即返回,并在后台对内存进行异步操作。它需要一个额外的 IntPtr,它会在操作完成时传回我的托管代码。可以同时运行多个此类操作。
我将指向非托管内存的指针封装在自定义 SafeBuffer 实例中,我希望在异步操作完成时取回该实例。 SafeBuffer 确保在没有对它的引用时正确释放内存。问题是当非托管函数仍在使用内存时,当然不应释放内存。
我怎样才能做到这一点?非托管函数被调用了数十亿次,因此性能至关重要。
我可以在调用该函数时分配一个 GCHandle,在操作完成时使用它来取回 SafeBuffer,然后释放它。然而,分配句柄似乎很昂贵,而且性能会随着时间的推移而显着下降。
我可以分配一个 GCHandle 一次,但是当非托管函数未使用内存并且没有对 SafeBuffer 的引用时,非托管内存不会被释放。
有什么想法吗?
最佳答案
您可以在托管端保留一个查找表:
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
,它是稳定的(不会改变)并且可以传递给非托管代码。
关于c# - 在非托管异步操作期间保持对象事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17708576/