防止在非托管代码中使用的托管引用的垃圾回收

时间:2013-02-06 17:47:54

标签: c# garbage-collection c++-cli wrapper

我的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()内的主动等待也不好。

2 个答案:

答案 0 :(得分:12)

您可以使用GCHandle.Alloc (voxelArr, GCHandleType.Pinned )手动固定阵列,以便GC不会移动或清除它。

当您知道方法已完成时,您将需要Free句柄,这将需要某种形式的回调才能完成。

答案 1 :(得分:1)

您当前方法的另一种选择:

考虑再次使数组全局化,在开始时创建并固定一次,然后在需要时重复使用它。不应该随心所欲地创建像这些一样大的对象pool them。只有当你需要用更大的尺寸重新创建它时才取消固定并释放它

将对象存储在全局池中将防止它被垃圾回收。严格来说,你不必担心固定这么大的物体,但这样做是为了保持一致性