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

Windows Forms Discussion :

[C# 2.0] Problème pour vider une imagelist


Sujet :

Windows Forms

  1. #1
    Membre habitué
    Homme Profil pro
    Mickaël
    Inscrit en
    Mai 2003
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Mickaël
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2003
    Messages : 106
    Points : 133
    Points
    133
    Par défaut [C# 2.0] Problème pour vider une imagelist
    Bonjour,

    Dans mon appli, je charge une imageList avec les images contenues dans un dossier (Environ 500). L'appli occupe a ce moment, 100Mo.

    A la fermeture, je parcours l'imageList et je fais un dispose sur chaque image, la mémoire utilisée augmente d'environ 60Mo par image que je dispose, jusqu'à l'exception fatale "out of memory".

    Normalement le dispose d'une image ne devrait pas faire grossir la mémoire non ?
    Pour tester, après chaque dispose j'ai ajouté un GC.Collect, la consommation de mémoire reste stable.. Par contre la libération des 500 images dure presque 1 minute.

    Connaissez-vous des solutions ou une méthode efficace pour vider une imageList ?

    Voilà la code de ma fonction de nettoyage :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
     while ( list.Images.Count > 0 )
    {
       try
        {
             list.Images[ 0 ].Dispose();
               //           GC.Collect();
     
       }
       catch
       {
     
       }
     
       list.Images.RemoveAt( 0 );
    }
    Merci,
    Nova Music Player, lecteur de musique pour win10
    http://novamusic.fpc-france.com

  2. #2
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    A la fermeture ...
    A la fermeture de l'application ? De l'écran utilisant le composant ImageList ?

    Dans les 2 cas de toute façon, inutile de boucler pour faire un Dispose de chaque image car :

    • on peut appeler la méthode Dispose du ImageList tout simplement
    • à la fermeture de l'application, la mémoire sera forcément réclamée
    • à la fermeture de l'écran le Dispose du Form sera appelé (sauf si non affiché ou affiché en ShowDialog, il faudra appeler la méthode explicitement à ce moment). La méthode Dispose du composant ImageList aussi donc
    Pas de questions techniques par MP

  3. #3
    Membre habitué
    Homme Profil pro
    Mickaël
    Inscrit en
    Mai 2003
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Mickaël
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2003
    Messages : 106
    Points : 133
    Points
    133
    Par défaut
    Merci,

    D'après mes tests, Dispose sur l'imageList ne libère pas la mémoire des images de la liste. C'est aussi ce que j'ai pu lire sur le net.

    En réalité, ces images sont affichées dans un onglet, et je libère la mémoire lorsque l'utilisateur ferme un onglet. Ce n'est pas forcement à la fermeture de l'application.
    Si je ne libère pas la mémoire à ce moment là, la mémoire sera rapidement saturée si l'utilisateur ouvre plusieurs onglets.
    Nova Music Player, lecteur de musique pour win10
    http://novamusic.fpc-france.com

  4. #4
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    N'est tu pas en train de réinventer la roue ?

    Je pense qu'un clear devrait suffire !
    Et apres tu peux faire un dispose de ton imagelist
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  5. #5
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Ce qui est sûr c'est que tu peux éviter le problème de dépassement de mémoire. Le problème vient de ton traitement de nettoyage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    while ( list.Images.Count > 0 )
    {
       try
       {
             list.Images[ 0 ].Dispose();
       }
       catch { } 
       list.Images.RemoveAt( 0 );
    }
    tu vas alors déclencher la création d'un nouveau tableau à chaque image (Array.Copy afin de copier les données dans un autre tableau de taille N-1). Histoire de valider mes dires, voici ce que l'on peut voir avec Reflector
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public virtual void RemoveAt(int index)
    {
        if ((index < 0) || (index >= this._size))
        {
            throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
        }
        this._size--;
        if (index < this._size)
        {
            Array.Copy(this._items, index + 1, this._items, index, this._size - index);
        }
        this._items[this._size] = null;
        this._version++;
    }
    cela va augmenter la mémoire à chaque création de tableau. Plus tu as d'images, plus tu vas recréer des tableaux, plus la mémoire va augmenter, la mémoire allouée pour les tableaux intermédiaires n'étant pas immédiatement réclamée.

    Alors qu'un simple
    ou encore, si le composant ImageList sert ailleurs (et donc le disposer serait source de problème)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    foreach (Image img in list.Images)
    {
        img.Dispose();
    }
    list.Images.Clear();
    permet d'éviter ce phénomène.

    Après si la mémoire ne baisse pas ce n'est pas forcément un problème, c'est que si Windows n'a pas besoin de mémoire alors le processus la garde au besoin à mon avis (quelqu'un confirmera peut être).

    Par exemple je lance un chargement d'image, je passe à 160Mo de mémoire pour le processus. Après libération des images je reste à 160Mo. Je refais un chargement, la mémoire augmente sur le coup mais à la fin je suis à 100-120Mo de mémoire pour le processus. Après d'autres chargement/libération le processus s'est stabilisé à 190Mo de mémoire.
    Pas de questions techniques par MP

  6. #6
    Membre habitué
    Homme Profil pro
    Mickaël
    Inscrit en
    Mai 2003
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Mickaël
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2003
    Messages : 106
    Points : 133
    Points
    133
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    foreach (Image img in list.Images)
    {
        img.Dispose();
    }
    list.Images.Clear();
    J'ai essayé ce code pour vider l'imageList.
    Avec 500 images affichées, la mémoire occupée est d'envirion 100Mo.
    Lors de la boucle, la mémoire occupée atteint et dépasse 1Go... ce qui provoque une exception OutOfMemory.
    Nova Music Player, lecteur de musique pour win10
    http://novamusic.fpc-france.com

  7. #7
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Ah ouais quand même

    Si seulement j'arrivais à reproduire le phénomène ^^
    Pas de questions techniques par MP

  8. #8
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    As tu essayé tout simplement un

    Sans faire ta boucle de dispose
    Je pense que le clear fait tout tout seul !
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  9. #9
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Citation Envoyé par olibara Voir le message
    Je pense que le clear fait tout tout seul !
    Le Clear videra la liste mais c'est tout. Si on ne fait pas de libération explicite (méthode Dispose), il faudra attendre que le GC fasse son travail (libération implicite avec le finaliseur). Une fois que l'objet n'est plus référencé, 1er passage du GC pour mettre l'objet dans la file d'attente des objets à finaliser, 2ème passage pour l'appel du finaliseur, 3ème passage pour la récupération de la mémoire. Au final cela fait trainer la libération (on ne contrôle pas le passage du GC, non déterministe).

    Néanmoins il peut tout de même tester pour voir ce qu'il se passe. S'il y a encore une augmentation de la mémoire c'est qu'il y a autre chose je pense.
    Pas de questions techniques par MP

  10. #10
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    MVP
    Thursday, July 13, 2006 12:51 PM0 votes
    Vote As Helpful
    ImageList inherits its Dispose() method from Component. Component.Dispose() does nothing but remove the component from the container.

    ImageList does have a protected virtual void Dispose


    http://social.msdn.microsoft.com/For...8-d3cfaee2338e
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  11. #11
    Membre habitué
    Homme Profil pro
    Mickaël
    Inscrit en
    Mai 2003
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Mickaël
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2003
    Messages : 106
    Points : 133
    Points
    133
    Par défaut
    Bonjour,

    J'ai refais des tests avec un peu tout ce qui est dis ici.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    foreach (Image img in list.Images)
    {
        img.Dispose();
    }
    Lors de la première entrée dans la boucle, l'exécution de list.Images fait monter la mémoire à + de 1Go. Sur XP, la mémoire utilisée monte jusqu'au plantage, sur Vista, ça se stabilise

    Si je fais ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while ( list.Images.Count > 0 )
     {
      list.Images[ 0 ].Dispose();
      GC.Collect();
    }
    la mémoire ne grimpe pas, mais le temps de traitement est super long (+ de 30s).


    Dernier test, je ne fais pas de dispose sur chaque image, juste un Clear de la liste et un dispose dessus. Traitement instantané, et la mémoire redescend aussitôt au niveau initial.

    Voilà, je marque ca comme résolu.
    Merci à tous pour m'avoir mis sur la piste.
    Nova Music Player, lecteur de musique pour win10
    http://novamusic.fpc-france.com

  12. #12
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Dernier test, je ne fais pas de dispose sur chaque image, juste un Clear de la liste et un dispose dessus. Traitement instantané, et la mémoire redescend aussitôt au niveau initial.
    Je suis content que ca marche !
    Et je suis aussi content de l'avoir dis et que c'est bien la bonne méthode !
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème pour vider une ListBox
    Par djames37 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 07/08/2011, 19h13
  2. Problème pour vider une combobox multicolonne
    Par kgb1917 dans le forum Windows Forms
    Réponses: 11
    Dernier message: 31/01/2010, 23h58
  3. Réponses: 13
    Dernier message: 23/12/2004, 18h01
  4. [MSSQL] Problème pour sélectionner une seule occurence
    Par Tinfolley dans le forum Langage SQL
    Réponses: 4
    Dernier message: 02/07/2004, 09h02
  5. Réponses: 3
    Dernier message: 29/08/2003, 10h57

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