代码之家  ›  专栏  ›  技术社区  ›  Dax Fohl

要调用需要intptr的方法,最好使用/unsafe或marshal.allochglobal吗?

  •  0
  • Dax Fohl  · 技术社区  · 15 年前

    我有一个类,在应用程序的整个过程中有几个实例是持久的。这些对象都需要调用一个dll方法,该方法从现有的float[]缓冲区追加数据,并将完整的数据集传递给一个dll方法,该方法每秒接受几次intptr(float array)。作为非托管代码是否更好:

    
    
        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 (可能相当大)在清理内存空间时。这是合理的考虑吗?建议是否取决于排列大小?

    2 回复  |  直到 15 年前
        1
  •  3
  •   Reed Copsey    15 年前

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

    我更喜欢第二种选择——它更干净,更容易理解,更明显。它也不会强制您收集数组的IDisposable。

        2
  •  2
  •   Dax Fohl    15 年前

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