Senza indicarmi MSDN, qualcuno potrebbe fornire una spiegazione concisa e chiara dello scopo di ciascuno di questi e quando utilizzarli. (IntPtr, SafeHandle e HandleRef)IntPtr, SafeHandle e HandleRef - Explained
risposta
IntPtr
è solo una semplice struttura integer che può contenere un puntatore (ad esempio, a 32 bit su sistemi a 32 bit, a 64 bit su sistemi a 64 bit).
SafeHandle
è una classe destinata a contenere gli handle di oggetti Win32 - ha un finalizzatore che si assicura che l'handle sia chiuso quando l'oggetto è GC. SafeHandle
è una classe astratta perché le diverse maniglie Win32 hanno diversi modi per cui devono essere chiusi. Prima dell'introduzione di SafeHandle
, IntPtr
veniva utilizzato per contenere gli handle di Win32, ma assicurarsi che fossero stati chiusi correttamente e impedire l'esecuzione di GC era responsabilità del programmatore.
HandleRef
è un modo per assicurarsi che un handle non gestito non venga eseguito da GC quando si è nel mezzo di una chiamata P/Invoke. Senza qualcosa come HandleRef
, se il codice gestito non fa nulla con l'handle dopo la chiamata P/Invoke, se il GC è stato eseguito durante la chiamata P/Invoke, non si renderebbe conto che l'handle era ancora in uso e potrebbe farlo con GC . Immagino (ma non sono sicuro e non ho guardato) che SafeHandle
potrebbe utilizzare HandleRef
come parte della gestione dell'handle incapsulato.
Correzione minima. Usa HandleRef quando non vuoi che un oggetto * gestito * GC venga inserito durante PInvoke. , ad esempio classe HWnd {handle IntPtr pubblico; } HWnd a = new HWnd(); B.SendMessage (a.Handle, ...); <- a potrebbe essere GC in PInvoke B.SendMessage (nuovo HandleRef (a, a.Handle)) <- ora non può essere GC in PInvoke –
Un'altra aggiunta: 'SafeHandle' include il conteggio dei riferimenti a evitare di gestire attacchi di riciclaggio. –
Qualcuno può confermare che maneggevolezza utilizza handleref?O almeno ha un meccanismo simile? – Assimilater
HWnd a = new HWnd();
B.SendMessage(a.Handle, ...);
Assumendo questo è l'unico riferimento "a" nel programma, questo equivale a:
HWnd a = new HWnd();
IntPtr h = a.Handle;
// a is no longer needed and thus can be GC'ed
B.SendMessage(h, ...);
Il problema è che quando "a" è disposto, si chiuderà la maniglia. Se ciò accade prima o durante la chiamata a SendMessage, l'handle non sarà valido.
HandleRef impedisce a "a" di essere raccolto prima che il programma abbia terminato h.
Sembra SafeHandle non incorporare il comportamento KeepAlive del HandleRef: Project Roslyn SafeHandle.cs http://referencesource.microsoft.com/#mscorlib/system/runtime/interopservices/safehandle.cs,743afbddafaea263
/*
Problems addressed by the SafeHandle class:
1) Critical finalization - ensure we never leak OS resources in SQL. Done
without running truly arbitrary & unbounded amounts of managed code.
2) Reduced graph promotion - during finalization, keep object graph small
3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread ---- (HandleRef)
<...>
*/
Ma io non sono sicuro, sembra che il comportamento keepalive può essere acheived solo fornendo falso valore al costruttore che semplicemente contrassegna l'oggetto come non definibile, quindi devi chiamare SafeHandle's Dispose() per evitare perdite di risorse in quel caso, ho ragione? Qualcuno può spiegare il codice sorgente, qual è il
private extern void InternalDispose();
private extern void InternalFinalize();
?
- 1. Posso usare SafeHandle invece di IntPtr?
- 2. C# usa IDisposable o SafeHandle?
- 3. Differenza tra IntPtr e UIntPtr
- 4. Copia dati da IntPtr a IntPtr
- 5. Qual è la differenza tra HandleRef e GCHandle?
- 6. .NET Interop IntPtr vs. ref
- 7. Come convertire IntPtr a int
- 8. nuova IntPtr (0) vs. IntPtr.Zero
- 9. Come liberare IntPtr in C#?
- 10. perché non è possibile confrontare IntPtr.Zero e default (IntPtr)?
- 11. C# - Come convertire oggetti in IntPtr e Back?
- 12. System :: IntPtr to int * in C++/CLI
- 13. Conversione da HWND a IntPtr (CLI)
- 14. C# Process.MainWindowHandle restituisce sempre IntPtr Zero
- 15. Come ottenere un IntPtr in una struct?
- 16. C# come ottenere Byte [] da IntPtr
- 17. Converti array di strutture in IntPtr
- 18. Copia dall'array IntPtr (16 bit) all'host gestito
- 19. Come allocare array di IntPtr [] nella memoria non gestita?
- 20. È possibile ottenere un IntPtr da un array int []?
- 21. C# deallocate la memoria a cui fa riferimento IntPtr
- 22. Perché IntPtr non ha bisogno della parola chiave non sicura?
- 23. Convertire un handle di finestra IntPtr in IWin32Window^
- 24. Come eseguire il cast di IntPtr su byte *
- 25. C# Posso controllare se un IntPtr è nullo?
- 26. rendere IntPtr in C# .NET al valore stringa
- 27. C#, valore di parametro predefinito per un IntPtr
- 28. Come posso pin (e ottenere un IntPtr a) un array T [] generico?
- 29. Il parametro è un'eccezione non valida quando si utilizza Graphics.GetHdc
- 30. IntPtr.Zero equivale a null?
Cosa c'è che non va con MSDN? –
Niente. Sto solo cercando un breve riassunto di ciascuno per assicurarmi che li stia usando correttamente. Se leggo MSDN e le descrizioni di altre persone, ho una sensazione migliore se quello che sto facendo è corretto. – user62572