Для вызова метода, требующего IntPtr, лучше использовать /unsafe или Marshal .AllocHGlobal?

StackOverflow https://stackoverflow.com/questions/1682776

Вопрос

У меня есть класс, который будет иметь несколько экземпляров, постоянных на протяжении всего срока действия приложения.Каждому из этих объектов потребуется вызвать метод dll, который добавляет данные из существующего буфера float[] и передает полный набор данных в метод DLL, который принимает IntPtr (массив float), несколько раз в секунду.Лучше ли делать это как неуправляемый код:



    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?

Это было полезно?

Решение 2

В конце концов я понял, что оба решения хороши.Производительность примерно такая же, и GC не окажет влияния на 2-е решение, поскольку объект либо будет выделен в кучу больших объектов и никогда не будет перемещен, либо быстро будет повышен до 2-го поколения в сборщике мусора и перемещается очень редко.

Другие советы

В обоих случаях вы вызываете собственный небезопасный код.

Я предпочитаю второй вариант - он более чистый, понятный и более очевидный.Это также не навязывает вам IDisposable для сбора вашего массива.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top