我的C#应用程序使用包装的C ++代码进行计算。
C ++标题:
__declspec(dllexport) void SetVolume(BYTE* data, unsigned int width);
C ++ / CLI包装器:
void SetVolume(array<Byte>^ data, UInt32 width)
{
cli::pin_ptr<BYTE> pdata = &data[0];
pal->SetVolume(pdata, width);
}
C#:
public startCalc()
{
byte[] voxelArr = File.ReadAllBytes("Filtered.rec");
palw.SetVolume(voxelArr, 490);
//GC.KeepAlive(voxelArr); makes no sense
}
C ++ SetVolume
函数启动异步计算。管理端不再引用voxelArr
并且是垃圾回收。
如果非托管代码完成它的工作而不将voxelArr
声明为全局变量,那么如何防止此引用的垃圾收集?创建数组副本不是一个选项,因为实际上有很多数据。 startCalc()
内的主动等待也不好。
答案 0 :(得分:12)
您可以使用GCHandle.Alloc
(voxelArr,
GCHandleType.Pinned
)
手动固定阵列,以便GC不会移动或清除它。
当您知道方法已完成时,您将需要Free句柄,这将需要某种形式的回调才能完成。
答案 1 :(得分:1)
您当前方法的另一种选择:
考虑再次使数组全局化,在开始时创建并固定一次,然后在需要时重复使用它。不应该随心所欲地创建像这些一样大的对象pool them。只有当你需要用更大的尺寸重新创建它时才取消固定并释放它
将对象存储在全局池中将防止它被垃圾回收。严格来说,你不必担心固定这么大的物体,但这样做是为了保持一致性