c# - 在非托管异步操作期间保持对象事件

标签 c# garbage-collection .net-4.5 unmanaged

我正在使用一个非托管函数,该函数采用指向某个非托管内存的指针。该函数在调用时立即返回,并在后台对内存进行异步操作。它需要一个额外的 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/

相关文章:

c# - 无法将类型 'System.Action<int>' 转换为 'System.Action<object>'

c# - MEF错误 "Only one batch can be composed at a time"

c# - 从用户控件访问表单

java - 在 Java 中查找内存使用情况

.net - 在 Windows 10 上安装 .Net 4.5(缺少 4.5 和 4.6 版本)

c# - 正则表达式只匹配不以 ")"结尾的字符串

c# - C# 中的对象创建问题

memory-management - D 动态阵列 - RAII

javascript - 如何在 Javascript (Node.js) 中将 "new"对象标记为垃圾回收

c# - 测试时间是否是第二天,不包括午夜