Cosa sono esattamente le risorse non gestite?


Risposte:


177

Le risorse gestite in pratica significano "memoria gestita" gestita dal Garbage Collector. Quando non hai più riferimenti a un oggetto gestito (che utilizza la memoria gestita), Garbage Collector rilascerà (eventualmente) quella memoria per te.

Le risorse non gestite sono quindi tutto ciò che il garbage collector non conosce. Per esempio:

  • Apri file
  • Apri connessioni di rete
  • Memoria non gestita
  • In XNA: buffer di vertici, buffer di indice, trame, ecc.

Normalmente si desidera rilasciare quelle risorse non gestite prima di perdere tutti i riferimenti che si hanno all'oggetto che le gestisce. Puoi farlo chiamando Disposequell'oggetto o (in C #) usando l' usingistruzione che gestirà la chiamata Disposeper te.

Se trascuri Disposecorrettamente le tue risorse non gestite, il Garbage Collector alla fine lo gestirà per te quando l'oggetto che contiene quella risorsa è garbage collection (questa è "finalizzazione"). Ma poiché il garbage collector non è a conoscenza delle risorse non gestite, non può dire quanto male debba liberarle, quindi è possibile che il tuo programma funzioni male o esaurisca completamente le risorse.

Se implementi tu stesso una classe che gestisce risorse non gestite, spetta a te implementare Disposee Finalizecorrettamente.


7
La connessione Open Database rientra in quale categoria? Gestito / Non gestito?
Deviprasad Das

8
+1 Altre risposte mancano il punto importante che stai chiamando Dispose su un oggetto gestito che gestisce internamente la liberazione della risorsa non gestita che avvolge (ad es. Handle di file, GDI + bitmap, ...) e che se accedi direttamente alle risorse non gestite ( PInvoke ecc.) Devi gestirlo.
Ian Mercer,

2
@Dev: non gestito - poiché il GC non lo conosce (supponendo che non si stia utilizzando un ipotetico database di memoria gestita). Ma l'oggetto connessione stesso potrebbe non contenere una risorsa non gestita. Presumibilmente la connessione al database utilizza un file aperto o una connessione di rete da qualche parte - ma è possibile che un altro oggetto (diverso dall'oggetto connessione) stia gestendo quella risorsa non gestita (forse la libreria del database memorizza le connessioni nella cache). Controlla la documentazione e vedi dove ti chiede di chiamare Disposeo usare using.
Andrew Russell,

11
Ho un commento / domanda di base su questo, posso mettere in relazione un oggetto come gestito / non gestito solo dal tipo, ad esempio, la stringa è gestita, DataSet non è gestito (motivo per cui ha un metodo Dispose ()) , Le connessioni al database non sono gestite (perché hanno dispose), ecc. Quindi è il presupposto, se ha un metodo "Dispose ()", allora non è gestito? Inoltre, quale sarebbe un oggetto XmlDocument? Grazie
Ganders,

15
@ganders Questa è una buona regola empirica. Tuttavia, tenere presente che tutte le istanze della classe C # sono oggetti gestiti. Se un'istanza di una classe può contenere risorse non gestite, tale classe deve implementare IDisposable. Se una classe non implementa IDisposable, allora si dovrebbe disporre di istanze di quella classe con usingo Dispose()quando si è fatto con loro. Sulla base di questo, il tuo contrario detiene: Se una classe implementa IDisposable, probabilmente contiene risorse non gestite internamente.
Andrew Russell,

56

Alcuni utenti classificano i file aperti, le connessioni db, la memoria allocata, le bitmap, i flussi di file ecc. Tra le risorse gestite, altri tra quelli non gestiti. Quindi sono gestiti o non gestiti?

La mia opinione è che la risposta sia più complessa: quando apri un file in .NET, probabilmente usi una classe .NET integrata System.IO.File, FileStream o qualcos'altro. Poiché è una normale classe .NET, è gestita. Ma è un wrapper, che al suo interno fa il "lavoro sporco" (comunica con il sistema operativo usando Win32 DLL, chiamando funzioni di basso livello o addirittura istruzioni assembler) che aprono davvero il file. E questo è ciò che .NET non sa, non gestito. Ma forse puoi aprire il file da solo usando le istruzioni assembler e bypassando le funzioni dei file .NET. Quindi l'handle e il file aperto sono risorse non gestite.

Lo stesso con il DB: se usi un assembly DB, hai classi come DbConnection ecc., Sono note a .NET e gestite. Ma avvolgono il "lavoro sporco", che non è gestito (allocare memoria sul server, stabilire una connessione con esso, ...). Se non usi questa classe wrapper e apri un socket di rete da solo e comunichi con il tuo strano database usando alcuni comandi, non è gestito.

Queste classi wrapper (File, DbConnection ecc.) Sono gestite, ma al loro interno usano risorse non gestite allo stesso modo di te, se non usi i wrapper e fai il "lavoro sporco" da solo. E quindi questi wrapper implementano i modelli Dispose / Finalize. È loro responsabilità consentire al programmatore di rilasciare risorse non gestite quando il wrapper non è più necessario e di rilasciarle quando il wrapper viene raccolto. Il wrapper verrà correttamente raccolto dall'immondizia dal Garbage Collector, ma le risorse non gestite all'interno verranno raccolte utilizzando il modello Dispose / Finalize.

Se non si utilizzano classi wrapper .NET o di terze parti integrate e file aperti da alcune istruzioni assembler, ecc. Nella propria classe, questi file aperti non sono gestiti e DEVE implementare il modello dispose / finalize. In caso contrario, si verificherà una perdita di memoria, una risorsa bloccata per sempre ecc. Anche quando non la si utilizza più (operazione di file completata) o anche dopo la chiusura dell'applicazione.

Ma la tua responsabilità è anche quando usi questi wrapper. Per coloro che implementano dispose / finalize (li riconosci, che implementano IDisposable), implementa anche il tuo pattern dispose / finalize e Dispose anche questi wrapper o dai loro il segnale per liberare le loro risorse non gestite. In caso contrario, le risorse saranno disponibili dopo un periodo di tempo indefinito, ma è opportuno rilasciarlo immediatamente (chiudere immediatamente il file e non lasciarlo aperto e bloccato per diversi minuti / ore a caso). Quindi nel metodo Dispose della tua classe chiami i metodi Dispose di tutti i wrapper usati.


1
Buona la chiarezza aggiuntiva suunmanaged vs managed resources
ora colui che non deve essere nominato.

grazie per la tua risposta. su quali classi si consiglia di chiamare effettivamente Dispose?
BKSpurgeon,

2
Questo è semplice Su ogni classe utilizzata, è necessario verificare se implementa l'interfaccia IDisposable. In caso affermativo, se si utilizza tale classe in un metodo (ad esempio: apertura del file, memorizzazione del testo, chiusura del file), è possibile utilizzare tale modello utilizzando () {}, che chiama automaticamente Dispose. Se usi tale classe in più metodi (es: la tua classe contiene File, nel costruttore apre il file, quindi diversi metodi aggiungono alcuni log ...), allora devi implementare l'interfaccia IDisposable dalla tua classe, implementare il modello Dispose / Finalize e disporre correttamente l'oggetto di quella classe.
Martas,

1
"... qualche classe .NET integrata System.IO.File, FileStream o qualcos'altro. Poiché è una normale classe .NET, è gestita." Con rispetto, questo è sbagliato e fuorviante. Non sono gestiti . Se fossero gestiti, allora potresti allocare queste classi e aspettarti che il garbage collector gestisca completamente la deallocazione di tutte le risorse in modo deterministico. Tuttavia, ciò comporterà il blocco e la conservazione degli handle di file e delle risorse non gestite per un periodo molto più lungo del necessario poiché il garbage collector non dislocerà la classe e non la finalizzerà potenzialmente per un tempo molto lungo.
AaronS

1
@AaronLS nel tuo commento hai parlato di "FileStream" riferendolo a come non gestito ma non lo è, anche se internamente utilizza risorse non gestite per fare il suo lavoro. Nel mondo gestito, Microsoft ti ha nascosto molte cose non gestite implementando il disporre il modello. Il codice gestito non significa che non utilizza risorse non gestite. Tuttavia, Microsoft ha svolto un buon lavoro nell'implementazione di IDisposable su questi tipi di oggetti. Ciò è dimostrato dal fatto che implementa IDisposable. Rispetto a tali prove dovremmo considerarlo un oggetto gestito.
Malik Khalil,

12

Le risorse non gestite sono quelle che vengono eseguite al di fuori del runtime .NET (CLR) (noto anche come codice non.NET). Ad esempio, una chiamata a una DLL nell'API Win32 o una chiamata a una DLL scritta in C ++.


6

Una "risorsa non gestita" non è una cosa, ma una responsabilità. Se un oggetto possiede una risorsa non gestita, ciò significa che (1) alcune entità al di fuori di esso sono state manipolate in modo da causare problemi se non ripulite e (2) l'oggetto ha le informazioni necessarie per eseguire tale pulizia ed è responsabile per averlo fatto.

Sebbene molti tipi di risorse non gestite siano fortemente associati a vari tipi di entità del sistema operativo (file, handle GDI, blocchi di memoria allocati, ecc.) Non esiste un singolo tipo di entità che è condivisa da tutti tranne la responsabilità di pulire. In genere, se un oggetto ha la responsabilità di eseguire la pulizia, avrà un metodo Dispose che gli ordina di eseguire tutta la pulizia di cui è responsabile.

In alcuni casi, gli oggetti tengono conto della possibilità che possano essere abbandonati senza che nessuno abbia prima chiamato Dispose. Il GC consente agli oggetti di richiedere la notifica di essere stati abbandonati (chiamando una routine chiamata Finalizza) e gli oggetti possono utilizzare questa notifica per eseguire la pulizia da soli.

Termini come "risorsa gestita" e "risorsa non gestita" sono, purtroppo, usati da persone diverse per indicare cose diverse; francamente penso che sia più utile pensare in termini di oggetti come non avere alcuna responsabilità per la pulizia, avere una responsabilità per la pulizia di cui ci si occuperà solo se si chiama Dispose o avere una responsabilità di pulizia che dovrebbe essere curata tramite Dispose, ma che può essere curato anche da Finalize.


5

La differenza fondamentale tra una risorsa gestita e non gestita è che il garbage collector conosce tutte le risorse gestite, a un certo punto il GC arriverà e ripulirà tutta la memoria e le risorse associate a un oggetto gestito. Il GC non è a conoscenza di risorse non gestite, come file, stream e handle, quindi se non li ripulisci esplicitamente nel tuo codice, finirai con perdite di memoria e risorse bloccate.

Rubato da qui , sentiti libero di leggere l'intero post.


2

Qualsiasi risorsa per la quale è allocata la memoria nell'heap gestito .NET è una risorsa gestita. CLR è completamente consapevole di questo tipo di memoria e farà di tutto per assicurarsi che non rimanga orfano. Qualsiasi altra cosa non è gestita. Ad esempio, interagendo con COM, è possibile creare oggetti nello spazio di memoria dei processi, ma CLR non se ne occuperà. In questo caso l'oggetto gestito che effettua chiamate attraverso la lavanderia gestita dovrebbe essere responsabile di qualsiasi cosa al di là di esso.


0

Cerchiamo innanzitutto di capire come venivano eseguiti i programmi VB6 o C ++ (applicazioni non Dotnet). Sappiamo che i computer comprendono solo il codice a livello di macchina. Il codice a livello di macchina è anche chiamato come codice nativo o binario. Quindi, quando eseguiamo un programma VB6 o C ++, il rispettivo compilatore del linguaggio, compila il rispettivo codice sorgente del linguaggio in codice nativo, che può quindi essere compreso dal sistema operativo e dall'hardware sottostanti.

Il codice nativo (Unmanaged Code) è specifico (nativo) per il sistema operativo su cui viene generato. Se prendi questo codice nativo compilato e provi a eseguirlo su un altro sistema operativo, fallirà. Quindi il problema con questo stile di esecuzione del programma è che non è portabile da una piattaforma all'altra.

Cerchiamo ora di capire come viene eseguito un programma .Net. Usando dotnet possiamo creare diversi tipi di applicazioni. Alcuni dei tipi più comuni di applicazioni .NET includono applicazioni Web, Windows, console e mobili. Indipendentemente dal tipo di applicazione, quando si esegue un'applicazione .NET si verifica quanto segue

  1. L'applicazione .NET viene compilata in Intermediate language (IL). IL è anche indicato come Common Intermediate language (CIL) e Microsoft Intermediate language (MSIL). Entrambe le applicazioni .NET e non .NET generano un assembly. Le assemblee hanno un'estensione di .DLL o .EXE. Ad esempio, se si compila un'applicazione Windows o Console, si ottiene un .EXE, dove come quando compiliamo un progetto di libreria Web o Class otteniamo un .DLL. La differenza tra un assembly .NET e NON .NET è che, DOTNET Assembly è in formato di lingua intermedio, mentre come assembly NON DOTNET è in formato di codice nativo.

  2. Le applicazioni NON DOTNET possono essere eseguite direttamente sul sistema operativo, mentre le applicazioni DOTNET vengono eseguite su un ambiente virtuale chiamato Common Language Runtime (CLR). CLR contiene un componente chiamato Just In-Time Compiler (JIT), che convertirà la lingua intermedia in codice nativo che il sistema operativo sottostante può comprendere.

Quindi, in .NET l'esecuzione dell'applicazione consiste in 2 passaggi 1. Compilatore di lingue, compila il codice sorgente in Intermediate Language (IL) 2. Il compilatore JIT in CLR converte, l'IL in codice nativo che può quindi essere eseguito sul sistema operativo sottostante .

Poiché un assembly .NET è in formato Intermedaite Language e non in codice nativo, gli assembly .NET sono portabili su qualsiasi piattaforma, purché la piattaforma di destinazione abbia Common Language Runtime (CLR). Il CLR della piattaforma di destinazione converte la lingua intermodita in codice nativo che può essere compreso dal sistema operativo sottostante. Intermediate Languge è anche chiamato come codice gestito. Questo perché CLR gestisce il codice che viene eseguito al suo interno. Ad esempio, in un programma VB6, lo sviluppatore è responsabile della disallocazione della memoria consumata da un oggetto. Se un programmatore dimentica di disallocare la memoria, potremmo incorrere in eccezioni difficili da eliminare. D'altra parte un programmatore .NET non deve preoccuparsi di disallocare la memoria consumata da un oggetto. La gestione automatica della memoria, nota anche come raccolta dei rifiuti, è fornita da CLR. A parte, dalla raccolta dei rifiuti, ci sono molti altri vantaggi forniti dal CLR, di cui parleremo in una sessione successiva. Poiché, CLR gestisce ed esegue l'Intermediate Language, esso (IL) viene anche chiamato come codice gestito.

.NET supporta diversi linguaggi di programmazione come C #, VB, J # e C ++. C #, VB e J # possono generare solo codice gestito (IL), dove C ++ può generare sia codice gestito (IL) che codice non gestito (codice nativo).

Il codice nativo non viene memorizzato in modo permanente da nessuna parte, dopo aver chiuso il programma il codice nativo viene eliminato. Quando eseguiamo nuovamente il programma, il codice nativo viene nuovamente generato.

Il programma .NET è simile all'esecuzione del programma java. In java abbiamo codici byte e JVM (Java Virtual Machine), dove come in .NET abbiamo Intermediate Language e CLR (Common Language Runtime)

Questo è fornito da questo link: è un ottimo tutor. http://csharp-video-tutorials.blogspot.in/2012/07/net-program-execution-part-1.html

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.