IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Destruction d'objets Dispose() Garbage Collector


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Par défaut Destruction d'objets Dispose() Garbage Collector
    Bonjour,

    Je cherche depuis pas mal de temps une méthode fiable pour détruire les objets de façon certaine.
    Pour fermer une "form", j'appelle la méthode Close() puis dans l'évènement FormClosed, j'appelle la méthode Dispose() pour toutes les ressources non managées et pour la form elle-même.

    Si je fais un recherche des contrôles qui ne seraient pas détruits, la recherche me dit bien que tous les objets sont bien détruits et apparamment déréférencés.

    Le problème est qu'en ouvrant ClrProfiler et en analysant via le gestionnaire de taches : il reste toujours quelques éléments de la form (ClrProfiler) et la mémoire n'est pas bien libérée.
    J'ai l'impression que le ramasse-miettes (Garbage Collector) est bien paresseux.

    J'ai donc essayé ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Try
                System.GC.Collect()
                System.GC.WaitForPendingFinalizers()
            Catch ex As Exception
            End Try
    Le "nettoyage" est immédiat et l'occupation mémoire reste contenue à chaque ouverture et fermeture de la "form".
    Je n'ai aucun retour d'erreur et le programme se comporte bien.

    Malheureusement, en parcourant le web, il est dit partout qu'il NE FAUT PAS utiliser le GC et le laisser travailler seul.

    Pour une form "lourde" de mon logiciel, si je n'utilise pas ces quatres lignes, j'ai une augmentation régulière de l'occupation mémoire et pourant je suis sur d'avoir libéré toutes les ressources non "managées" les bitmaps par exemple.

    Un éclaircissement serait le bienvenu.

    Merci d'avance.

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    ca peut être lié spécifiquement au code

    par exemple si tu as une variable bitmap dont tu remplaces le contenu plusieurs fois et que tu disposes sur le form closed, les instances précédemment stockées ici ne sont pas disposées (faire le dispose avant chaque remplissage de l'ancienne valeur si elle existe par exemple)

    quand on dispose un control, toute la hiérrarchie des enfants est disposée
    si tu avais remove un control pour faire un truc il n'est plus dans le lien de parenté et ne sera pas disposé

    etc...


    le but du GC n'est pas de vider la mémoire à tout prix et le plus rapidement possible, il passe quand il y a besoin, au final c'est surement moins gourmand
    de nos jours les pcs ont plusieurs Go de ram, qu'une appli prenne 50 ou 250 Mo de ram ca ne change rien pour windows et l'utilisateur
    normalement on voit une diminution cyclique de la ram au bout d'un certain usage, et si une appli a besoin de ram et qu'il n'y en a plus, le gc sera appelé donc pas de soucis non plus
    par contre ce fonctionnement va bien si on gère la mémoire dans l'appli
    une boucle qui fait des new bitmap et l'appli crash rapidement

    le using / end using est pratique aussi, il garanti l'appel du dispose même en cas de sortie de bloc comme une exception

    dans clr profiler tu dois pouvoir trouver les types des choses qui restent pour trouver la "fuite"


    concernant le GC.Collect s'il est accessible ca doit bien être pour une raison
    nous on a fait un thread qui gc.collect et thread.sleep(5 minutes) en boucle
    on a fait ca au début parce qu'on avait des soucis et surement pas tout compris, mais vu que ca ne dérange pas plus que ca on l'a laissé ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Par défaut
    Re,

    Merci pour la réactivité et la qualité de la réponse !

    Pour les bitmap, par exemple, lorsque je ferme la form la ressource est libérée.
    La variable bitmap est globale mais j'effectue un dispose() suivi d'une affectation à Nothing même si je dois la réutiliser par la suite.
    Sinon, de toute façon, c'est memory leak à tous les coups ! avec ou sans GC.

    Justement pour un exemple de fuite, sur un splashscreen très simple, j'ai essayé diverses méthodes sans résultats probants pour la libération : il n'y a qu'une image en background et des label.
    Même si je fais un dispose () manuel de tous les contrôles (je ne devrais pas avoir besoin de le faire Me.dispose est suffisant mais j'ai quand même essayé) , il y a des "restes" de label référencés dans ClrProfiler.
    La référence à ces label n'existent que dans la form.
    L'occupation est minime (20 K) après libération mais il reste des références dans ClrProfiler ?
    J'aimerai comprendre pourquoi ?

    Pour Using et end using, je verrai comment modifier mes lignes mais ce n'est pas simple sur une form qui a 15000 lignes de code.

    Donc pour résumer, le GC bosse quand il veut ou quand il est pressant de libérer et à son rythme.

    Pour l'appel du GC, je vois que tu l'utilises avec un thread dédié mais y-a t-il contre-indication à utiliser l'appel à collect à chaque sortie de form ?
    Car si c'est possible sans risque de pénaliser Windows ou le soft, le problème serait résolu.

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    Citation Envoyé par Pascal_F Voir le message
    La variable bitmap est globale mais j'effectue un dispose() suivi d'une affectation à Nothing même si je dois la réutiliser par la suite.
    la mise à nothing est automatique en sortie de bloc, les variables ne sont d'ailleurs pas utilisables hors du bloc
    concernant les variables de classes, elles sont mises à nothing sur le finalize si je me rappelle bien
    et donc le GC peut intervenir sur des variables non référencées par des choses "vivantes"
    le finalize c'est le truc que le GC appelle, sur les classes implémentant IDisposable, le dispose(false) est appelé à ce moment là, ce qui permet en théorie d'éviter tout fuite réelle

    Citation Envoyé par Pascal_F Voir le message
    Sinon, de toute façon, c'est memory leak à tous les coups ! avec ou sans GC.
    oui et non je pense, cf au dessus
    le truc bien pour les fuites c'est addhandler sans removehandler

    Citation Envoyé par Pascal_F Voir le message
    L'occupation est minime (20 K) après libération mais il reste des références dans ClrProfiler ?
    J'aimerai comprendre pourquoi ?
    moi aussi


    Citation Envoyé par Pascal_F Voir le message
    Pour Using et end using, je verrai
    pour le coup c'est le truc anti fuite
    c'est quasiment indispensable, ca équivaut à un try finally, les classes de connexions aux données par exemple dans le dispose font le .close sur la connexion
    sur un code de type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    try
      conn.open
      cmd.executenonquery
      conn.dispos
    catch
      ...
    ici en cas d'erreur la connexion reste ouverte, on peut s'en sortir avec d'autres méthodes que le using mais le using est quand même plus pratique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    try
      using conn
        conn.open
        cmd.executenonquery
      end using
    catch
      ...
    là même dans le catch conn.dispose sera appelé et donc la connexion fermée

    Citation Envoyé par Pascal_F Voir le message
    ce n'est pas simple sur une form qui a 15000 lignes de code.
    au dessus de 1000 lignes de code dans un form c'est un soucis de conception ou d'utilisation de .net
    si tu veux je peux jeter un oeil à ton code pour te dire ce qu'il y a de raté

    Citation Envoyé par Pascal_F Voir le message
    Donc pour résumer, le GC bosse quand il veut ou quand il est pressant de libérer et à son rythme.
    c'est ça

    Citation Envoyé par Pascal_F Voir le message
    Pour l'appel du GC, je vois que tu l'utilises avec un thread dédié mais y-a t-il contre-indication à utiliser l'appel à collect à chaque sortie de form ?
    Car si c'est possible sans risque de pénaliser Windows ou le soft, le problème serait résolu.
    ca ne peut pas pénaliser windows, ca ne peut pénaliser que ton appli
    normalement ca peut être bloquant, c'est pour ca qu'on le fait sur un thread séparé (bien qu'il parrait que de toute facon ca verrouille tous les threads), sur une petite appli et un gros pc ca ne doit pas se voir
    après si ton appli n'est pas censé tourner h24 et qu'elle est petite normalement tu n'as pas besoin d'appeler gc.collect, à part pour voir baisser la ram prise, mais là on tombe dans le psychologique il faut surtout se dire qu'on est plus y a vingt an ou le moindre logiciel devait être optimisé niveau ram
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Par défaut
    L'application développée est du domaine de la phsyique appliquée (conditionnement de l'air humide).
    La page principale accueille au lancement un diagramme complexe qui est en fond de page ( ce fond de page n'est pas réactualisé sauf si il faut redessiner le diagramme dans certains cas; le bitmap est bien réinitialisé et il n'y a pas de problème de fuite de ce coté).

    Pour réaliser les évolutions sur ce diagramme, j'ai implémenter 12 modules différents qui sont regroupés chacun sur des panels qui sont cachés ou visibles suivant les besoins. Les panels acceuillent des contrôles (environ 350) qui sont actualisés à chaque action.

    Ce choix me permet :

    - de m'affranchir d'une gestion entre la fenêtre de fond qui doit être réactive ( évènements mousedown et mousemove) et l'affichage de l'interface pour entrer ou modifier des paramètres. Si j'avais choisis l'option de créer pour chaque module une fenêtre, il fallait à chaque fois l'intialiser avec les paramètres en cours. Il aurait fallu plus de code au total à chaque réinitialisation et ouverture d'une form secondaire

    - de réactualiser en fond de tâche chaque panel même si il n'est pas visible (action d'un module sur l'autre)

    - de gérer aussi facilement les fonctions Undo et redo à partir d'un memorystream sauvant les proprités principales des contrôles et le contenu des variables globales.

    - de sauver les différentes propriétés des paramètres dans ces panel dans un fichier et de les retrouver simplement à l'ouverture du fichier sans avoir à jongler avec les différents contrôles.

    Dans cette page, comme il y a beaucoup de contrôles,il y a aussi beaucoup d'évènements à gérer : j'ai regroupé les évènements par type pour diminuer la répétion des évènements équivalents et le nombre de lignes.

    Mais , il y a aussi une très grande quantité d'équations pour le calcul.
    C'est ce qui explique la grande quantité de lignes.
    Trop de Sub, pour scinder, ralentit l'éxécution du logiciel et la gestion est plus compliquée.



    J'ai quatre évènements dans l'ordre Removehandler puis AddHandler ( pour éviter des erreurs de stack : boucle infinie sur un texchanged par exemple).
    J'enlève l'évènement pour actualiser puis je le réintègre.
    Sur tes conseils, j'ai rajouté 4 Removehandler à la fermeture de la form.

    Je vais donc laisser le GC.collect que pour la page principale et ne pas l'utiliser pour le reste.
    Le logiciel ne tourne pas 24/24 et l'utilisateur ne s'amuse pas à ouvrir successivement la page principale.

Discussions similaires

  1. Le nombre d'objet à collecter par le garbage collector
    Par TaymouWan dans le forum VB.NET
    Réponses: 3
    Dernier message: 22/12/2009, 17h41
  2. Réponses: 9
    Dernier message: 06/05/2008, 17h10
  3. Réponses: 13
    Dernier message: 03/09/2007, 11h55
  4. Garbage Collector/libération objets référencés
    Par LeSmurf dans le forum Général Java
    Réponses: 3
    Dernier message: 17/12/2006, 19h47
  5. [JVM] les objets et le Garbage collector
    Par Kurdran dans le forum Général Java
    Réponses: 7
    Dernier message: 02/06/2005, 16h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo