Je veux savoir ce que sont les ressources non gérées. Quelqu'un peut-il me donner une idée de base ?
La connexion à une base de données ouverte relève de quelle catégorie ? Gérée / Non gérée ?
Je veux savoir ce que sont les ressources non gérées. Quelqu'un peut-il me donner une idée de base ?
Par ressources gérées, on entend essentiellement la "mémoire gérée" qui est gérée par le ramasseur d'ordures. Lorsque vous n'avez plus de références à un objet géré (qui utilise de la mémoire gérée), le ramasseur d'ordures libère (éventuellement) cette mémoire pour vous.
Les ressources non gérées sont alors tout ce que le ramasseur d'ordures ne connaît pas. Par exemple :
Normalement, vous voulez libérer ces ressources non gérées. avant vous perdez toutes les références que vous avez à l'objet qui les gère. Pour ce faire, vous appelez Dispose
sur cet objet, ou (en C#) en utilisant la fonction using
qui se chargera d'appeler Dispose
pour vous.
Si vous négligez de Dispose
de vos ressources non gérées correctement, le ramasseur d'ordures s'en chargera éventuellement pour vous lorsque l'objet contenant cette ressource sera ramassé (c'est la "finalisation"). Mais comme le ramasseur d'ordures ne connaît pas les ressources non gérées, il ne peut pas savoir à quel point il doit les libérer - il est donc possible que votre programme ait des performances médiocres 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, c'est à vous d'implémenter Dispose
et Finalize
correctement.
+1 Les autres réponses manquent le point important que vous appelez Dispose sur un géré qui gère en interne la libération de la ressource non gérée qu'il enveloppe (par exemple, un gestionnaire de fichier, un bitmap GDI+, ...) et que si vous accédez directement aux ressources non gérées (PInvoke, etc.), vous devez vous en charger.
@Dev : Non géré - car le GC ne le sait pas (en supposant que vous n'utilisez pas une hypothétique base de données en mémoire gérée). Mais l'objet de connexion lui-même ne peut pas contenir une ressource non gérée. La connexion à la base de données utilise probablement un fichier ouvert ou une connexion réseau. quelque part - mais c'est possible qu'un autre objet (autre que l'objet de connexion) gère cette ressource non gérée (peut-être que votre bibliothèque de base de données met en cache les connexions). Vérifiez la documentation et voyez où il vous est demandé d'appeler Dispose
ou utiliser using
.
Certains utilisateurs classent les fichiers ouverts, les connexions aux bases de données, la mémoire allouée, les bitmaps, les flux de fichiers, etc. parmi les ressources gérées, d'autres parmi les ressources non gérées. Alors, sont-ils gérés ou non gérés ?
À mon avis, la réponse est plus complexe : lorsque vous ouvrez un fichier en .NET, vous utilisez probablement une classe intégrée de .NET, System.IO.File, FileStream ou autre. Comme il s'agit d'une classe .NET normale, elle est gérée. Mais c'est une enveloppe qui, à l'intérieur, fait le "sale boulot" (communiquer avec le système d'exploitation à l'aide de dlls Win32, appeler des fonctions de bas niveau ou même des instructions assembleur) qui ouvre réellement le fichier. Et ceci est, ce que .NET ne sait pas, non géré. Mais vous pouvez peut-être ouvrir le fichier par vous-même en utilisant des instructions d'assembleur et en contournant les fonctions de fichier de .NET. Dans ce cas, l'identifiant et le fichier ouvert sont des ressources non gérées.
C'est la même chose avec la base de données : si vous utilisez un assemblage de base de données, vous avez des classes comme DbConnection, etc. Mais elles enveloppent le "sale boulot", qui n'est pas géré (allouer de la mémoire au serveur, établir une connexion avec lui, ...). Si vous n'utilisez pas cette classe enveloppante et que vous ouvrez un socket réseau par vous-même et communiquez avec votre propre base de données étrange en utilisant quelques commandes, c'est non géré.
Ces classes de wrappers (File, DbConnection etc.) sont gérées, mais elles utilisent à l'intérieur des ressources non gérées de la même manière que vous, si vous n'utilisez pas les wrappers et faites le "sale boulot" par vous-même. Par conséquent, ces wrappers mettent en œuvre les schémas Dispose/Finalize. Il est de leur responsabilité de permettre au programmeur de libérer les ressources non gérées lorsque le wrapper n'est plus nécessaire, et de les libérer lorsque le wrapper est mis au rebut. Le wrapper sera correctement ramassé par le ramasseur d'ordures, mais les ressources non gérées à l'intérieur seront ramassées en utilisant le pattern Dispose/Finalize.
Si vous n'utilisez pas les classes wrapper intégrées de .NET ou de tiers et que vous ouvrez des fichiers par des instructions d'assembleur, etc. dans votre classe, ces fichiers ouverts ne sont pas gérés et vous DEVEZ implémenter le pattern dispose/finalise. Si vous ne le faites pas, il y aura une fuite de mémoire, une ressource verrouillée à jamais, etc., même si vous ne l'utilisez plus (opération de fichier terminée) ou même après la fin de votre application.
Mais votre responsabilité est également engagée lorsque vous utilisez ces wrappers. Pour ceux qui implémentent dispose/finalise (vous les reconnaissez, car ils implémentent IDisposable), implémentez également votre pattern dispose/finalise et disposez même ces wrappers ou donnez-leur un signal pour 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 plus propre de les libérer immédiatement (fermez le fichier immédiatement et ne le laissez pas ouvert et bloqué pendant plusieurs minutes/heures). Ainsi, dans la méthode Dispose de votre classe, vous appelez les méthodes Dispose de tous les wrappers utilisés.
Merci pour votre réponse. Quelles sont les classes pour lesquelles il est recommandé d'appeler Dispose ?
C'est simple. Sur chaque classe que vous utilisez, vous devez vérifier, si elle implémente l'interface IDisposable. Si oui, alors si vous utilisez une telle classe dans une méthode (ex : ouverture du fichier, stockage du texte, fermeture du fichier), vous pouvez utiliser le pattern using() { }, qui appelle Dispose pour vous automatiquement. Si vous utilisez une telle classe dans plusieurs méthodes (ex : votre classe contient File, dans le constructeur elle ouvre le fichier, puis plusieurs méthodes ajoutent des logs...), alors vous devez implémenter l'interface IDisposable par votre classe, implémenter le pattern Dispose/Finalize et disposer correctement de l'objet de cette classe.
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 à l'objet a été manipulée d'une manière qui peut 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 de le faire.
Bien que de nombreux types de ressources non gérées soient très fortement associés à divers types d'entités du système d'exploitation (fichiers, handles GDI, blocs de mémoire alloués, etc.), il n'y a pas de type d'entité unique qui soit partagé par tous, si ce n'est la responsabilité du nettoyage. ), il n'y a pas de type d'entité unique qui soit partagé par tous, si ce n'est la responsabilité du nettoyage. Typiquement, si un objet a la responsabilité d'effectuer le nettoyage, il aura une méthode Dispose qui lui demandera d'effectuer tous les nettoyages dont il est responsable.
Dans certains cas, les objets prévoient la possibilité qu'ils soient abandonnés sans que personne n'ait appelé Dispose au préalable. La GC permet aux objets de demander une notification de leur abandon (en appelant une routine appelée Finalize), et les objets peuvent utiliser cette notification pour effectuer eux-mêmes le nettoyage.
Des termes comme "ressource gérée" et "ressource non gérée" sont, malheureusement, utilisés par différentes personnes pour signifier différentes choses ; franchement, je pense qu'il est plus utile de penser en termes d'objets comme n'ayant pas de responsabilité de nettoyage, ayant une responsabilité de nettoyage qui ne sera prise en charge que si Dispose est appelé, ou ayant une responsabilité de nettoyage qui devrait être prise en charge par Dispose, mais qui peut également être prise en charge par Finalize.
La différence fondamentale entre une ressource gérée et non gérée est que le ramasseur d'ordures le ramasseur de déchets connaît toutes les ressources gérées, à un moment donné le GC viendra nettoyer toute la mémoire et les ressources associées à un objet géré. à un objet géré. Le GC ne connaît pas les ressources non gérées, comme les fichiers, les flux et les handles. comme les fichiers, les flux et les handles. Si vous ne les nettoyez pas explicitement dans votre code votre code, vous vous retrouverez avec des fuites de mémoire et des ressources verrouillées.
Volé à ici N'hésitez pas à lire l'intégralité de l'article.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
1 votes
Voir aussi cette page, qui donne une explication fantastique et un modèle pour l'utilisation correcte de IDisposable, et comment prendre en compte les ressources non gérées : stackoverflow.com/questions/538060/