Per chiamare un metodo che richiede IntPtr, è meglio usare / non sicuri, o Marshal.AllocHGlobal?
-
18-09-2019 - |
Domanda
Ho una classe che avrà alcuni casi persistenti per tutta la durata dell'applicazione. Questi oggetti ciascun necessario chiamare un metodo DLL che aggiunge dati da un galleggiante [] tampone esistente, e passa l'intero set di dati a un metodo DLL che accetta un IntPtr (matrice float), più volte al secondo. E 'meglio farlo codice come non gestito:
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);
}
}
o sarebbe meglio utilizzare un tag non sicuri e fisso?
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);
}
}
}
C'è qualche vantaggio di non dover utilizzare il tag "non sicuro" nel compilatore? È la classe Marshal realtà qualsiasi "più sicuro"? Quale di questi metodi generalmente hanno la migliore prestazione?
I magra verso l'ex, proprio perché in questo modo il GC non deve preoccuparsi di _floats
(che potrebbe essere abbastanza grande) quando si pulisce lo spazio di memoria. che è una preoccupazione ragionevole? Ha la raccomandazione dipende dalle dimensioni del arraysize?
Soluzione 2
I definitiva imparato che entrambe le soluzioni vanno bene. Le prestazioni sono circa lo stesso e il GC non avrà un impatto sulla seconda soluzione, dal momento che l'oggetto sarebbe o essere assegnato al mucchio di oggetti di grandi dimensioni e non si mosse, o rapidamente essere promosso al 2 ° generazione sul garbage collector e si è trasferito molto raramente .
Altri suggerimenti
In entrambi i casi, si sta chiamando nativo, il codice non sicuro.
Io preferisco la seconda opzione - è più pulito, più facile da seguire, e più evidente. Inoltre non forzare IDisposable su di voi per l'array da riscuotere.