Question

Quelles ressources doivent être nettoyées manuellement dans C # et quelles sont les conséquences si vous ne le faites pas?

Par exemple, disons que j'ai le code suivant:

myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
// Use Brush

Si je ne nettoie pas le pinceau à l’aide de la méthode disposer, je suppose que le ramasse-miettes libère la mémoire utilisée à la fin du programme? Est-ce correct?

De quelles autres ressources ai-je besoin pour nettoyer manuellement?

Était-ce utile?

La solution

Techniquement, tout ce qui hérite d’IDisposable devrait être éliminé de manière proactive. Vous pouvez utiliser l'instruction 'using' pour simplifier les choses.

http://msdn.microsoft.com/en-us/library /yh598w02.aspx

Parfois, vous constaterez une utilisation incohérente des objets dérivés IDisposable dans l'exemple de code de la documentation, ainsi que du code généré par des outils (par exemple, Visual Studio).

Ce qui est intéressant avec IDisposable, c’est qu’il vous permet de libérer de manière proactive la ressource non gérée sous-jacente. Parfois, vous voulez vraiment faire cela - pensez aux connexions réseau et aux ressources de fichiers par exemple.

Autres conseils

Si vous ne jetez pas quelque chose, il sera nettoyé lorsque le ramasse-miettes remarquera qu'il n'y a plus de référence à cela dans votre code, ce qui peut être après un certain temps. Pour quelque chose comme ça, ça n'a pas vraiment d'importance, mais c'est probablement le cas pour un fichier ouvert.

En général, si quelque chose a une méthode Dispose, vous devez l'appeler lorsque vous avez terminé, ou, si vous le pouvez, l'envelopper dans une instruction à l'aide de :

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}
  • Manipulations des structures de données internes à Windows.
  • Connexions à la base de données.
  • Poignées de fichiers.
  • Connexions réseau.
  • Références COM / OLE.

La liste continue.

Il est important d'appeler Dispose ou mieux encore, utilisez le modèle à l'aide de .

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}

Si vous ne jetez pas quelque chose, il sera nettoyé lorsque le ramasseur de mémoire remarquera qu'il n'y a plus de référence à cela, ce qui pourrait être après un certain temps.

Dans le cas de System.Drawing.Brush , Windows conservera les structures de fenêtre internes du pinceau chargé en mémoire jusqu'à ce que tous les programmes libèrent leur descripteur.

Les conséquences de ne pas disposer de vos tablettes d’identité peuvent aller d’un impact négligeable sur les performances à un crash de votre application.

L'objet Pinceau de votre exemple sera nettoyé par le GC quand il en aura envie. Mais votre programme n'aura pas bénéficié de la quantité de mémoire supplémentaire que vous auriez gagnée en le nettoyant plus tôt. Si vous utilisez beaucoup d'objets Pinceau, cela peut devenir important. Le GC est également plus efficace pour nettoyer les objets s’ils n’ont pas été là depuis très longtemps, car il s’agit d’un ramasse-miettes générationnel.

D'autre part, si vous ne supprimez pas les objets de connexion à la base de données, vous risquez de manquer très rapidement de connexions de base de données en pool et de provoquer le blocage de votre application.

Soit utiliser

using (new DisposableThing...
{
    ...
}

Ou, si vous avez besoin de conserver une référence à un IDisposable dans votre objet pendant toute sa durée de vie, implémentez IDisposable sur votre objet et appelez la méthode Dispose d'IDisposable.

class MyClass : IDisposable
{
    private IDisposable disposableThing;

    public void DoStuffThatRequiresHavingAReferenceToDisposableThing() { ... }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    //etc... (see IDisposable on msdn)

}

En règle générale, tout ce qui implémente IDisposable devrait vous amener à faire une pause et à rechercher la ressource que vous utilisez.

La GC ne se produit que lorsque la mémoire est insuffisante, vous ne pouvez donc pas prédire quand. Bien qu'un déchargement de AppDomain le déclenche certainement.

Comme d’autres l’ont dit, l’utilisation est votre ami. J'ai écrit cette entrée de blog à propos de comment mettre en œuvre IDisposable de manière assez simple et moins sujette aux erreurs en prenant en compte les éléments les plus importants.

Un truc que j’utilise quand je ne me souviens pas si un objet est une ressource jetable consiste à taper ".Dispose". (au plus!) après la déclaration pour que Intellisense vérifie pour moi:

MemoryStream ms = new MemoryStream().Dispose

Supprimez ensuite le .Dispose et utilisez la directive using ():

using(MemoryStream ms = new MemoryStream())
{
  ...
}

Eh bien, tant que vous utilisez la version gérée des ressources et n'appelez pas les API Windows par vous-même, tout devrait bien se passer. Ne vous inquiétez que de devoir supprimer / détruire une ressource lorsque vous obtenez un IntPtr, comme "Windows". (et bien d’autres choses encore) sont connus dans .NET et non comme un objet.

Au fait, la ressource (comme tout autre objet .NET) sera marquée pour la collecte dès que vous quittez le contexte actuel. Ainsi, si vous créez le pinceau dans une méthode, il sera marqué lorsque vous le quitterez.

Si cela est géré (c'est-à-dire une partie du framework), vous n'avez pas besoin de vous en préoccuper. Si elle implémente IDisposable, enveloppez-la simplement dans un bloc utilisant .

Si vous souhaitez utiliser des ressources non gérées, vous devez vous informer sur les finaliseurs et implémenter vous-même IDisposable.

Il y a beaucoup plus de détails dans cette question

Tout d'abord, à la fin du programme, vous pouvez supposer que la mémoire utilisée par le processus sera éliminée avec le processus lui-même.

Lors de l'utilisation de dispose ou de destructor in.net, il faut comprendre que l'heure à laquelle la fonction de disposition est appelée par le GC est non déterministe. C’est pourquoi il est recommandé d’utiliser ou d’appeler explicitement le dispositif de disposition.

Lors de l'utilisation de ressources telles que des fichiers, les objets de mémoire tels que les sémaphores et les ressources résidant en dehors du monde géré de .net doivent être libérés.

Le SolidBrush, par exemple, vous devez en disposer, car il s’agit d’un objet GDI et n’habite pas dans le monde .net.

Le ramasse-miettes ne libère pas seulement à la fin du programme, sinon il ne serait pas vraiment utile (quel que soit le système d'exploitation, récent ou décent, lorsque le processus se ferme, toute la mémoire est automatiquement nettoyée par le système d'exploitation).

L'un des gros avantages du C # par rapport au C / C ++ est que vous n'avez pas à vous soucier de libérer des objets alloués (la plupart du temps au moins); le gc le fait quand le runtime décide (diverses stratégies quand / comment le faire).

De nombreuses ressources ne sont pas prises en charge par le gc: fichiers, ressources liées aux threads (verrous), connexions réseau, etc.

Les objets qui semblent paraissent petits au GC, mais ne le sont pas ... Dans l'API SharePoint, par exemple, l'objet SPWeb a une faible empreinte en ce qui concerne le GC et la priorité sera donc faible pour la collecte, mais elle a vraiment récupéré une quantité de mémoire (dans le tas, je crois) que le GC ne connaît pas. Vous rencontrerez des problèmes de mémoire amusants, par exemple, n'oubliez pas de toujours utiliser ou supprimer!

Plutôt que de penser à un objet comme étant "tenant" ressources qui doivent être libérées, il est préférable de penser en termes d'objet comme ayant modifié quelque chose (éventuellement en dehors de l'ordinateur!) qui le survivra, d'une manière qui pourrait être néfaste s'il n'était pas défait ou "nettoyé", mais que seul l'objet peut nettoyer. Bien que cette altération prenne généralement la forme d’un objet concret dans une piscine marquée «occupé», sa forme précise importe peu. Ce qui compte, c'est que les modifications doivent être annulées et que l'objet contienne les informations nécessaires pour le faire.

Le ramasse-miettes traitera toutes les ressources gérées. Dans votre exemple, le pinceau sera nettoyé à la décision du ramasse-miettes, ce qui se produira quelque temps après que la dernière référence au pinceau n’est plus valide.

Certains éléments doivent être nettoyés manuellement, mais il s’agit de pointeurs récupérés à partir de sources non gérées, tels que les appels de DLL. Toutefois, rien dans le .NET Framework n’a besoin de ce traitement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top