0

我有一个类将在整个应用程序期间持续存在一些实例。这些对象都需要调用一个 dll 方法,该方法从现有的 float[] 缓冲区中附加数据,并将完整的数据集传递给一个接受 IntPtr(浮点数组)的 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);
            }
        }
    }

不必在编译器中使用“不安全”标签有什么好处吗?元帅级实际上是否“更安全”?这些方法中哪一种通常具有更好的性能?

_floats我倾向于前者,只是因为这样 GC在清理内存空间时不必担心(这可能非常大)。这是一个合理的担忧吗?建议是否取决于 ArraySize 的大小?

4

2 回答 2

3

在这两种情况下,您都在调用本机的、不安全的代码。

我更喜欢第二种选择——它更干净、更容易理解、更明显。它也不会强制您使用 IDisposable 来收集您的阵列。

于 2009-11-05T18:59:24.133 回答
2

我最终了解到这两种解决方案都很好。性能大致相同,GC 不会对第二个解决方案产生影响,因为对象要么被分配到大对象堆并且从不移动,要么在垃圾收集器上快速提升到第二代并且很少移动.

于 2009-11-16T17:38:25.157 回答