我有一个类,在整个应用程序期间会有一些持久化的实例。这些对象将需要调用一个dll方法,该方法从现有的float []缓冲区附加数据,并将完整数据集传递给接受IntPtr(float数组)的DLL方法,每秒几次。将其作为非托管代码更好:
class PersistentThing : IDisposable {
readonly IntPtr _floats = Marshal.AllocHGlobal(sizeof(float) * ArraySize);
public void DoFrequentAction() {
// Append data from a buffer to the memory space.
var floatOffsetPtr = new IntPtr(_floats.ToInt32() + _floatsIndex * sizeof(float));
Marshal.Copy(_buffer, _bufferIndex, floatOffsetPtr, _bufferCount);
// Call a DLL method with with memory pointer
CallDllMethod(_floats);
}
// Need to dispose the unmanaged memory
public void Dispose() {
Marshal.FreeHGlobal(_floats);
}
}
或者使用不安全的标签并修复会更好吗?
class PersistentThing2 {
readonly float[] _floats = new float[ArraySize];
public unsafe void DoFrequentAction() {
// Append data from a buffer to the memory space.
Array.Copy(_buffer, _bufferIndex, _floats, _floatsIndex, _bufferCount);
// Call a DLL method with with memory pointer
fixed (float* floatsPtr = _floats) {
CallDllMethod((IntPtr)floatsPtr);
}
}
}
是否有任何优势,不必在编译器中使用“unsafe”标签?元帅级实际上是否更“安全”?哪种方法通常具有更好的性能?
我倾向于前者,只是因为GC在清理内存空间时不必担心_floats
(可能非常大)。这是一个合理的担忧吗?建议是否取决于ArraySize的大小?
答案 0 :(得分:3)
在这两种情况下,您都在调用原生的,不安全的代码。
我更喜欢第二种选择 - 它更干净,更容易理解,更明显。它也不会强制您使用IDisposable来收集阵列。
答案 1 :(得分:2)
我最终了解到两种解决方案都很好。性能大致相同,GC不会对第二个解决方案产生影响,因为对象将被分配给大对象堆并且从未移动,或者很快被提升到垃圾收集器上的第二代并且很少移动