J'ai un certain nombre de classes qui ont des variables membres privées qui mettent en œuvre IDisposable (minuteries, brosses, etc.). Ai-je besoin de tout faire pour assurer ces variables sont nettoyés correctement par le .NET Framework? P>
La littérature que je suis venu à travers fait référence aux « ressources gérées » par rapport aux « ressources non gérés ». Ces termes me sont source de confusion parce que vous pouvez avoir une classe gérée qui implémente des fonctionnalités en utilisant des ressources non gérés. Est-ce considéré comme une « ressource non gérée » ou « ressource gérée »? P>
Si je comprends bien, si vous n'êtes pas appeler Dispose () sur un objet qui implémente IDisposable, alors les ressources ne sont pas libérées tant que la sortie de l'application. Cette situation pourrait provoquer des exceptions OutOfMemory lors de l'exécution du programme pendant une longue période de temps. P>
Comment puis-je être sûr que mon code est le bon déroulement gestion des ressources? Il est important pour ces objets parce qu'ils sont des contrôles personnalisés et il peut y avoir beaucoup de dessin qui consomme des ressources IDisposable. J'utilise le C # using chaque fois que je peux, mais parfois je dois faire un objet qui implémente IDisposable une variable membre, et la déclaration à l'aide ne me aider. P>
7 Réponses :
Oui - Si votre classe "contient" un Les ressources "gérées" sont fondamentalement la mémoire. Les ressources "non gérées" peuvent être des poignées de fichier, des connexions réseau, des poignées aux objets graphiques, etc. Dans la plupart des cas, les types directs em> accès aux poignées natives ont des finaliseurs. La ressource sera donc libérée à un moment donné, mais Il est toujours préférable de le libérer explicitement - dans certains cas (par exemple avec Si possible, il est plus gentil pas em> d'avoir de tels membres de classe en premier lieu - les avoir comme paramètres de méthode des variables locales, etc., afin que vous puissiez les utiliser, puis les fermer sans attacher la durée de vie de la ressource à la durée de vie de votre objet. Cependant, dans certains cas, ce n'est pas approprié - dans quel cas vous devriez mettre en œuvre Idisposable code>, cette classe doit presque em> implémenter
idisposable code> aussi. p>
httpwebreffonse code>), il peut y avoir un nombre limité de ces ressources disponibles (connexions dans un pool de connexion à un seul hôte dans ce cas) et vous peut finir par chronométrer dans l'attente d'une ressource «morte» à libérer. p>
Idisposable code>. P>
Je pense qu'il est important de noter que les ressources "non gérées" peuvent être pratiquement n'importe quoi, et n'importe où; Ils peuvent exister entièrement dans le monde géré (par exemple, une classe qui alloue des articles à partir d'une piscine détenue dans un tableau statique de manière à minimiser la pression de GC) ou peut exister quelque part autre que la machine actuelle (par exemple, une machine distante peut avoir obtenu des exclusives exclusives. accès à un enregistrement de base de données). Fondamentalement, tout ce que le GC ne saura pas nettoyer.
Si votre classe a des variables de membre qui implémentent Idisposable, votre classe devrait également la mettre en œuvre. Vous nettoyez ce que vous possédez. P>
1) Vous pouvez utiliser un outil de profil de mémoire, il y en a beaucoup autour du Web, le mieux que je connaisse d'être le profileur des fourmis de Reg Gate. P>
2) Ma règle de base est que les événements doivent toujours être désinscrits et les objets jetables (flux, etc.) seront automatiquement disposés si elles sont des variables membres et l'objet qui les détient est détruit.
Si vous créez un objet jetable local dans une méthode par exemple, vous devez le disposer ou simplement le mettre dans un en utilisant la déclaration code> et l'oublier;) p>
Vous avez de bonnes informations et certaines désinformations à votre compréhension. P>
Le long et court signifie que vous devez Etre comme ce sont des variables de membre privé de votre classe, Si ces variables de membre privé ont une durée de vie limitée (c'est-à-dire dans une seule méthode), il suffit de les envelopper dans un Dispose () code> tout ce qui implémente
Idisposable code>. P>
Idisposable code > et
jetez () code> de ces types dans son propre
jetez () code> méthode. P>
en utilisant le bloc CODE>. P>
Les directives iDisposables très complètes sont ici < / a>. p>
éliminer de manière transitoire les champs jetables définis dans votre type
de votre méthode de jet. strong> p>
Vous devez appeler () sur tous les champs
Dont le cycle de vie de votre objet contrôle. Par exemple, envisagez un cas
où votre objet possède un champ de Textreader privé. Dans votre type
Disposer, vous devriez appeler le dispositif d'élimination de l'objet Textreader, qui sera
à son tour, disposez de ses champs jetables (flux et codage, pour
exemple), et ainsi de suite. Si mis en œuvre à l'intérieur d'un dispositif (BOOL disposant)
méthode, cela ne devrait se produire que si le paramètre de disposition est
True-toucher d'autres objets gérés n'est pas autorisé pendant
finalisation. En outre, si votre objet ne possède pas une donnée
objet jetable, il ne devrait pas tenter de le disposer, comme d'autres
le code pourrait toujours compter sur elle être actif. Ces deux pourraient conduire à
bogues subtils à détecter. p>
Ce modèle
fournit un moyen normalisé pour les développeurs de déterminisciquement
Détruire ou des ressources libres appartenant à un objet. Il aident également les sous-classes
Pour libérer correctement les ressources de la classe de base. P>
blockQuote>
"ressource non gérée" fait généralement référence aux cas où votre code renvoie des poignées natales
Une ressource gérée est tout ce qui implémente Depuis que vous avez une classe de ressources gérées, suivez la règle 2: Implémente Idisposable code>. Une ressource non gérée est quelque chose comme un
gérer code> que vous avez eu via p / invoke. Une classe comme
SafeHandle code> (ou une dérivée de
SafeHandle code>) possède une ressource non gérée, mais elle est considérée comme une ressource gérée elle-même. Donc, toute classe qui possède une ressource non gérée est elle-même une ressource gérée. P>
Idisposable code> (mais pas un finisseur). P>
Idisposable code> permet un nettoyage antérieur. Si vous ne l'appelez pas, les ressources seront nettoyées de toute façon (elles ne seront pas suspendues avant la sortie du processus); Ils seront simplement nettoyés plus tard et vous n'avez pas le choix de quand em> ils sont nettoyés. P>
Merci pour la réponse claire. C'est ce que je cherchais. J'ai vu tant de blogs avec des informations conflictuelles. La page que vous avez liée est simple et claire.
Votre réponse s'applique-t-elle toujours si je vous dis que la classe hérite du contrôle et n'est pas scellée? Le contrôle a déjà une méthode de disposition.
Héritage des ressources gérées est plus complexe. Microsoft a leur Posséder un modèle plutôt déroutant pour cela. Ce que je recommande est: Remplacer Dispose (bool) code> (appelant
base.dispose (BOOL) code>) et disposez de vos ressources gérées uniquement si
true code> est passé dans cette méthode. Sinon, ne rien faire. Dans cette situation, votre classe ne devrait pas avoir de ressources non gérées.
Certaines classes qui implémentent Idisposables seront correctement nettoyées si elles sont abandonnées. Tous ne seront cependant pas tous, cependant. Si une interatrogue appelle une "déclaration de rendement" dans un verrou, l'itémérateur renvoyé par cet itérateur est abandonné sans être épargner, la serrure ne sera jamais libérée.
Personnellement, je n'appellerais pas "tout ce qui implique de mettre en œuvre Idisposable" une ressource gérée - en particulier, je serait i> de la mémoire d'appeler une ressource gérée, et c'est géré par le collectionneur de la poubelle - alors que j'appellerais tout ce qui bénéficie de l'opinion explicite Nettoyage non géré, directement (une poignée natale ") ou indirectement (via un autre type CLR).
@Jon: Je vois votre point sur la terminologie, mais je souhaite distinguer les ressources natives brutes et les ressources enveloppées CLR. Microsoft utilise parfois les termes "Ressource gérée" pour tout Idisposable < / Code>, et autres fois utilise le (imo maladroit) " Objets gérés qui utilisent des ressources natives »pour se reporter à des types jetables.
@Stephen: Je pense qu'il est raisonnable de faire la distinction entre ces deux, mais je parle généralement de types qui ont un accès direct aux ressources non gérées et à ceux qui ont un accès indirect.
Stephen, j'ai suivi votre suggestion de disposer de département (Bool). J'appelle toujours la base.Dispose (Bool). J'appelle Dispose sur la minuterie si le BOOL est défini sur True. J'ai exécuté le programme dans le débogueur avec un point d'arrêt défini en haut de cette méthode. Le point d'arrêt a été touché après l'application.exit a été appelé, mais le Bool est passé était faux, alors la méthode n'a donc pas exécuté la minuterie.Dispose. C'est le contraire de ce que je m'attendais à arriver.
@Trevor: Ceci est attendu (et correct) si vous n'appelez jamais disposer code> sur votre classe dérivée. Dans ce cas, votre
Dispose code> est appelé à partir du finaliseur.
Je pense qu'il est utile de décrire une ressource gérée est un objet de type de classe qui implémente Idisposable et nécessite un nettoyage, mais peut effectuer un tel nettoyage (généralement à l'aide de finaliser) si elle est abandonnée sans être abandonnée correctement. Une ressource non gérée se réfère généralement à une entité qui nécessite un nettoyage qui ne se produira tout simplement pas si elle est abandonnée sans être en premier. Il est important de noter que le terme "ressource géré" désigne essentiellement exclusivement des objets de type classe (qui remplacent généralement la finalisation, mais dans certains cas peut être les objectifs d'objets d'affaitation), des ressources non gérées peuvent être non seulement Quelque chose i>, ils peuvent aussi être n'importe où i>, y compris sur un autre ordinateur. P>
Je suggérerais que au lieu d'utiliser le terme "ressource", il est plus utile de penser en termes de "responsabilités". L'ouverture d'une connexion de fichier ou de socket crée une responsabilité de la fermer. L'acquisition d'un verrou crée une responsabilité de le libérer. Envoi d'un système distant un message «Accord-moi d'accès exclusif à cet enregistrement» Message crée une responsabilité de l'envoyer un message «J'en ai fait avec cet enregistrement». Si les responsabilités de nettoyage d'un objet peuvent être effectuées même si elle est abandonnée, c'est une "ressource gérée". Sinon, c'est une "ressource non gérée". P>
Sans simplement catégoriser les choses comme "ressources gérées" ou "ressources non gérées" n'est pas tout à fait suffisante pour décider de la manière dont ils devraient être nettoyés. Certaines responsabilités non gérées peuvent être correctement gérées par une enveloppe de type classe pouvant effectuer tout nettoyage nécessaire en cas d'abandon incorrect. Ces wrappers devraient généralement contenir une quantité minimale d'informations nécessaires pour assumer la responsabilité du nettoyage. D'autres responsabilités ne peuvent pas très bien être traitées automatiquement. Il est souvent préférable de s'assurer que l'élimination est appelé que d'essayer de gérer tout ce qui peut arriver si ce n'est pas le cas. P>
FYI - Si vous voulez plus d'informations, j'ai écrit sur ce scénario ici: REEDCOPSEY.com/2009/04/19/...