Je veux en savoir plus sur les ressources non gérées ... Tout le monde peut-il me donner une idée de base?
Ressources gérées signifie essentiellement "mémoire gérée" gérée par le ramasse-miettes. Lorsque vous n'avez plus aucune référence à un objet géré (qui utilise la mémoire gérée), le ramasse-miettes libère (éventuellement) cette mémoire pour vous.
Les ressources non gérées représentent alors tout ce que le ramasse-miettes ne connaît pas. Par exemple:
Normalement, vous souhaitez libérer ces ressources non gérées avant vous perdez toutes vos références à l’objet qui les gère. Pour ce faire, vous appelez Dispose
sur cet objet ou (en C #) à l’aide de l’instruction using
qui gérera l’appel de Dispose
à votre place.
Si vous négligez correctement Dispose
de vos ressources non gérées, le ramasse-miettes le gérera éventuellement pour vous lorsque l'objet contenant cette ressource est ramassé (c'est la "finalisation"). Mais comme le ramasse-miettes ne connaît pas les ressources non gérées, il ne sait pas à quel point il est nécessaire de les libérer - il est donc possible que votre programme fonctionne mal ou qu'il manque complètement de ressources.
Si vous implémentez vous-même une classe qui gère des ressources non gérées, vous devez implémenter correctement les variables Dispose
et Finalize
.
Certains utilisateurs classent les fichiers ouverts, les connexions à la base de données, la mémoire allouée, les bitmaps, les flux de fichiers, etc. parmi les ressources gérées, les autres parmi les non gérés. Alors sont-ils gérés ou non gérés?
Mon opinion est que la réponse est plus complexe: lorsque vous ouvrez un fichier dans .NET, vous utilisez probablement une classe .NET intégrée, System.IO.File, FileStream ou autre chose. Comme il s’agit d’une classe .NET normale, elle est gérée. Mais c’est un wrapper qui, à l’intérieur, fait le «sale boulot» (communique avec le système d’exploitation à l’aide des dlls Win32, appelle des fonctions de bas niveau ou même des instructions pour l’assemblage) qui ouvre réellement le fichier. Et voici ce que .NET ne sait pas, non géré . Mais vous pouvez peut-être ouvrir le fichier vous-même en utilisant les instructions de l'assembleur et contourner les fonctions de fichier .NET. Ensuite, le descripteur et le fichier ouvert sont des ressources non gérées.
Idem avec la base de données: si vous utilisez un assemblage de base de données, vous avez des classes telles que DbConnection, etc., elles sont connues de .NET et gérées. Mais ils encapsulent le "travail sale", qui est non géré (allouer de la mémoire sur le serveur, établir une connexion avec, ...) . Si vous n'utilisez pas cette classe wrapper et ouvrez vous-même une socket réseau et communiquez avec votre propre base de données étrange en utilisant certaines commandes, il est non géré.
Ces classes de wrapper (File, DbConnection, etc.) sont gérées, mais utilisent des ressources non gérées de la même manière que vous, si vous n'utilisez pas les wrappers et effectuez vous-même le "sale boulot". Et par conséquent, ces wrappers mettent en œuvre les modèles Dispose/Finalize. Il leur incombe de permettre au programmeur de libérer des ressources non gérées lorsque le wrapper n’est plus nécessaire, et de les libérer lorsque le wrapper est nettoyé. Le wrapper sera correctement collecté par garbage collector, mais les ressources non gérées qui s'y trouvent seront collectées à l'aide du modèle Dispose/Finalize.
Si vous n'utilisez pas de classes wrapper .NET ou tierce partie intégrées et de fichiers ouverts à l'aide d'instructions d'assembleur, etc. dans votre classe, ces fichiers ouverts ne sont pas gérés et vous DEVEZ mettre en œuvre un modèle dispose/finalize. Sinon, il y aura une fuite de mémoire, une ressource à jamais verrouillée, etc. même si vous ne l'utilisez plus (opération du fichier terminée) ou même après la fermeture de votre application.
Mais votre responsabilité est également lorsque vous utilisez ces emballages. Pour ceux qui implémentent dispos/finalize (vous les reconnaissez, qu'ils implémentent IDisposable), implémentez également votre modèle dispos/finalize et supprimez même ces wrappers ou donnez-leur le signal de libérer leurs ressources non gérées. Si vous ne le faites pas, les ressources seront libérées après un temps indéfini, mais il est temps de le libérer immédiatement (fermez le fichier immédiatement et ne le laissez pas ouvert et bloqué pendant plusieurs minutes/heures au hasard). Ainsi, dans la méthode Dispose de votre classe, vous appelez les méthodes Dispose de tous vos wrappers utilisés.
Les ressources non gérées sont celles qui fonctionnent en dehors du runtime .NET (CLR) (code non-.NET.) Par exemple, un appel à une DLL dans l'API Win32 ou un appel à un .dll écrit en C++. .
Une "ressource non gérée" n'est pas une chose, mais une responsabilité. Si un objet possède une ressource non gérée, cela signifie que (1) une entité extérieure à celle-ci a été manipulée de manière à causer des problèmes si elle n'est pas nettoyée, et (2) l'objet possède les informations nécessaires pour effectuer ce nettoyage et est responsable. pour le faire.
Bien que de nombreux types de ressources non gérées soient très fortement associés à divers types d’entités de système d’exploitation (fichiers, descripteurs GDI, blocs de mémoire alloués, etc.), il n’existe pas de type unique d’entité partagé par tous. que la responsabilité du nettoyage. Généralement, si un objet a la responsabilité d'effectuer le nettoyage, il disposera d'une méthode Dispose qui lui indiquera d'exécuter tout le nettoyage dont il est responsable.
Dans certains cas, les objets tiendront compte de la possibilité qu'ils puissent être abandonnés sans que personne ne l'ait appelé au préalable. Le GC permet aux objets de demander à être notifiés qu'ils ont été abandonnés (en appelant une routine appelée Finalize), et les objets peuvent utiliser cette notification pour effectuer eux-mêmes le nettoyage.
Des termes tels que "ressource gérée" et "ressource non gérée" sont, malheureusement, utilisés par différentes personnes pour signifier différentes choses; pense franchement qu’il est plus utile de penser en termes d’objets soit comme n’ayant aucune responsabilité de nettoyage, une responsabilité de nettoyage qui ne sera prise en charge que si Dispose est appelé, ou une responsabilité de nettoyage devant être prise en charge via Dispose, mais pouvant également être pris en charge par Finalize.
La différence fondamentale entre une ressource gérée et une ressource non gérée réside dans le fait que le récupérateur de mémoire Connaît toutes les ressources gérées, à un moment donné Le GC va venir nettoyer toute la mémoire et les ressources associées Avec un objet géré. Le GC ne connaît pas les ressources non gérées, telles que les fichiers, les flux et les handles. Par conséquent, si vous ne les nettoyez pas explicitement dans Votre code, vous obtiendrez des fuites de mémoire et des ressources verrouillées.
Volé de ici , n'hésitez pas à lire le post en entier.
Toute ressource pour laquelle de la mémoire est allouée dans le segment de mémoire géré .NET est une ressource gérée. CLR est parfaitement conscient de ce type de mémoire et fera tout ce qui est en son pouvoir pour qu’elle ne devienne pas orpheline. Tout le reste n'est pas géré. Par exemple, l'interopérabilité avec COM peut créer des objets dans l'espace mémoire du processus, mais le CLR ne s'en occupera pas. Dans ce cas, l'objet géré qui passe des appels à travers la frontière gérée doit assumer la responsabilité de tout ce qui se trouve au-delà de celui-ci.
Voyons d'abord comment les programmes VB6 ou C++ (applications Non Dotnet) exécutaient ..... Nous savons que les ordinateurs ne comprennent que le code au niveau de la machine. Le code de niveau machine est également appelé code natif ou binaire. Ainsi, lorsque nous exécutons un programme VB6 ou C++, le compilateur de langage respectif compile le code source du langage respectif en code natif, qui peut ensuite être compris par le système d'exploitation et le matériel sous-jacents.
Le code natif (code non géré) est spécifique (natif) au système d'exploitation sur lequel il est généré. Si vous prenez ce code natif compilé et essayez de l'exécuter sur un autre système d'exploitation, il échouera. Le problème avec ce style d’exécution de programme est donc qu’il n’est pas portable d’une plate-forme à une autre.
Voyons maintenant comment un programme .Net s'exécute. En utilisant dotnet, nous pouvons créer différents types d’applications. Parmi les types d’applications .NET les plus courants, citons les applications Web, Windows, console et mobiles. Quel que soit le type de l'application, les événements suivants se produisent lorsque vous exécutez une application .NET
L'application .NET est compilée en langage intermédiaire (IL). IL est également appelé langage CIL (Common Intermediate Language) et MSIL (Microsoft Intermediate Language). Les applications .NET et non .NET génèrent un assemblage. Les assemblys ont une extension .DLL ou .EXE. Par exemple, si vous compilez une application Windows ou une console, vous obtenez un fichier .exe, où, lorsque nous compilons un projet de bibliothèque Web ou de classe, nous obtenons un fichier .DLL. La différence entre un assemblage .NET et NON .NET est que, DOTNET Assembly est au format de langage intermédiaire, tandis que NON DOTNET Assembly est au format de code natif.
Les applications NON DOTNET peuvent s'exécuter directement sur le système d'exploitation, les applications DOTNET s'exécutant également sur un environnement virtuel appelé CLR (Common Language Runtime). CLR contient un composant appelé Just In-Time Compiler (JIT), qui convertira le langage intermédiaire en code natif que le système d'exploitation sous-jacent peut comprendre.
Ainsi, dans .NET, l’exécution de l’application se compose de 2 étapes 1. Compilateur de langage, compile le code source en langage intermédiaire (IL) 2. Le compilateur JIT dans CLR convertit l’IL en code natif qui peut ensuite être exécuté sur le système d’exploitation sous-jacent.
Dans la mesure où un assemblage .NET est au format de langage Intermedaite et non pas en code natif, les assemblys .NET sont portables sur n’importe quelle plate-forme, à condition que la plate-forme cible dispose du Common Language Runtime (CLR). Le CLR de la plate-forme cible convertit le langage Intermedaite en code natif que le système d'exploitation sous-jacent peut comprendre. Languge intermédiaire est également appelé code managé. En effet, CLR gère le code qui y est exécuté. Par exemple, dans un programme VB6, le développeur est responsable de la désallocation de la mémoire utilisée par un objet. Si un programmeur oublie de dé-allouer de la mémoire, il peut être difficile de détecter des exceptions de mémoire insuffisante. D'un autre côté, un programmeur .NET n'a pas à s'inquiéter de la désallocation de la mémoire utilisée par un objet. La gestion automatique de la mémoire, également appelée collecte de déchets, est fournie par le CLR. Outre le ramassage des ordures ménagères, le CLR offre plusieurs autres avantages, dont nous discuterons dans une session ultérieure. Étant donné que CLR gère et exécute le langage intermédiaire, celui-ci (IL) est également appelé code géré.
.NET prend en charge différents langages de programmation tels que C #, VB, J # et C++. C #, VB et J # ne peuvent générer que du code managé (IL), tandis que le C++ peut générer à la fois du code managé (IL) et du code non managé (code natif).
Le code natif n'est pas stocké de manière permanente, où que ce soit. Après la fermeture du programme, le code natif est jeté. Lorsque nous exécutons le programme à nouveau, le code natif est généré à nouveau.
Le programme .NET est similaire à l'exécution du programme Java. En Java, nous avons des codes d'octet et JVM (Java Virtual Machine), où, comme dans .NET, nous utilisons le langage intermédiaire et le CLR (Common Language Runtime).
C'est fourni à partir de ce lien - c'est un excellent tuteur . http://csharp-video-tutorials.blogspot.in/2012/07/net-program-execution-part-1.html