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 :

Libérer une variable


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Technicien Qualité Logiciel
    Inscrit en
    Janvier 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien Qualité Logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2010
    Messages : 44
    Par défaut Libérer une variable
    Bonjour à tous,

    Je viens vers vous pour savoir s'il était possible de libérer une variable (vider son contenu) ?

    Car j'ai un petit problème de mémoire sur un programme qui doit rechercher des images dans un dossier spécifique, voici le code :

    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    Private Sub ChargementTiles()
     
            ' Déclaration des variables
            Dim sImageTrouve() As String
            Dim sCheminTiles As String = Application.StartupPath & "\Tiles"
            Dim sFormatImage As String = "*.png"
            Dim sNomTiles As String
            Dim MonImage As System.Drawing.Bitmap
            Dim TailleX, TailleY As Integer
     
            ' Vider la liste déroulante
            Me.COMBO_TILES.Items.Clear()
     
            ' On parcourt le dossier des Tiles
            sImageTrouve = Directory.GetFileSystemEntries(sCheminTiles, sFormatImage)
            For Each ListeImage As String In sImageTrouve
                ' Ajout du nom du Tiles dans la liste déroulante
                sNomTiles = Mid(ListeImage, sCheminTiles.Length + 2)
                Me.COMBO_TILES.Items.Add(sNomTiles)
                ' On récupére la taille de l'image
                MonImage = New System.Drawing.Bitmap(ListeImage)
                TailleX = MonImage.Width
                TailleY = MonImage.Height
                ' Ajout dans la liste des Tiles
                Dim Tiles As New ClassTiles(sNomTiles, ListeImage, TailleX, TailleY)
                Me.ListeTiles.Add(Tiles)
            Next
     
            ' Vérifier si des tiles ont été trouvé
            If sImageTrouve.Count = 0 Then
                MsgBox("Aucun Tiles n'a été trouvé dans " & sCheminTiles & ".", MsgBoxStyle.Critical + MsgBoxStyle.OkOnly, "Tiles non trouvés.")
                Application.Exit()
            Else
                ' On sélection le premier Tiles dans la combobox
                Me.COMBO_TILES.SelectedIndex = 0
            End If
     
        End Sub
    Donc je lance cette procédure au démarrage de mon programme, elle permet de rechercher dans un dossier "Tiles" les image de format .png.
    Puis dans une classe nommé ClassTiles, je stock le chemin de l'image, sa taille et son nom.

    En déboguant pas à pas, je me suis rendu compte que c'était la variable "MonImage", que j'utilise pour charger l'image en mémoire afin de récupérer sa taille, qui cumule la taille de l'image à chaque boucle.

    Du coup si j'ai beaucoup d'image à rechercher, à l'ouverture, l'application pése déjà + de 100 mo...
    Puis si je la réduis et la maximise, elle perd toutes sa mémoire et descend à 20 mo (surement du au Garbadge collector ?)

    Du coup je voulais "vider" ma variable "MonImage" à chaque boucle en faisant :

    Mais ça ne fonctionne pas.

    Vous avez une idée sur la manière de procédé ?
    J'ai peut être mal pensé la récupération des images ?

    Surtout que je pensais que les variables étaient détruites après que les procédures soient terminées...

    Je vous remercie d'avance pour vos conseils.

    Bonne journée!
    Cryo

  2. #2
    Membre éprouvé Avatar de LeCygne
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2010
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2010
    Messages : 91
    Par défaut
    Je ne suis pas specialiste de la mémoire, mais j'aurais tendance à dire: Sauf problème de performance, faites confiance au garbage collector, il se declenchera au momment où il le faut.

    Vous pouvez tout de même l'aider un peu :

    Le "Nothing", c'est très bien.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MonImage = Nothing
    En ajoutant un "Dispose" avant, c'est encore mieu. Dispose force l'objet à liberer les ressources qu'il utilise lui même:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    MonImage.Dispose()
    MonImage = Nothing
    Une autre méthode à essayer, consiste à ne pas créer, utiliser puis détruire un objet image à chaque iteration, mais plutot de le créer avant la boucle, l'utiliser pendant la boucle, et le detruire après.
    Le fait de faire un "new" à chaque iteration, fait que vous abandonnez la reference de votre ancien objet "Image" pour en cree un nouveau, ce qui réalloue de la mémoire. Vous pouvez, à la place, faire un "FromFile()"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MonImage.FromFile("filename As String")
    Sans avoir verifié, cela donnerait :
    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
    17
    18
    19
    20
     
            MonImage = New System.Drawing.Bitmap()
     
            ' On parcourt le dossier des Tiles
            sImageTrouve = Directory.GetFileSystemEntries(sCheminTiles, sFormatImage)
            For Each ListeImage As String In sImageTrouve
                ' Ajout du nom du Tiles dans la liste déroulante
                sNomTiles = Mid(ListeImage, sCheminTiles.Length + 2)
                Me.COMBO_TILES.Items.Add(sNomTiles)
                ' On récupére la taille de l'image
                MonImage.FromFile(ListeImage)
                TailleX = MonImage.Width
                TailleY = MonImage.Height
                ' Ajout dans la liste des Tiles
                Dim Tiles As New ClassTiles(sNomTiles, ListeImage, TailleX, TailleY)
                Me.ListeTiles.Add(Tiles)
            Next
     
            MonImage.Dispose()
            MonImage = Nothing

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par LeCygne Voir le message
    Je ne suis pas specialiste de la mémoire, mais j'aurais tendance à dire: Sauf problème de performance, faites confiance au garbage collector, il se declenchera au momment où il le faut.
    Tout à fait
    Pour vérifier que le GC va bien collecter la mémoire, tu peux l'appeler explicitement :

    Mais c'est pas conseillé, fais le juste pour voir que ça libère effectivement la mémoire et enlève le après.

    Citation Envoyé par LeCygne Voir le message
    Vous pouvez tout de même l'aider un peu :

    Le "Nothing", c'est très bien.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MonImage = Nothing
    Non, en l'occurrence ça sert à rien (pour une variable locale), parce la variable va sortir du scope à la fin de la méthode de toutes façons, et sera éligible pour le GC

    Citation Envoyé par LeCygne Voir le message
    En ajoutant un "Dispose" avant, c'est encore mieu. Dispose force l'objet à liberer les ressources qu'il utilise lui même:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    MonImage.Dispose()
    MonImage = Nothing
    Le Dispose est effectivement une bonne habitude, ça permet de libérer tout de suite les ressources système associées à l'objet (handle HBITMAP par exemple)

    Citation Envoyé par LeCygne Voir le message
    Une autre méthode à essayer, consiste à ne pas créer, utiliser puis détruire un objet image à chaque iteration, mais plutot de le créer avant la boucle, l'utiliser pendant la boucle, et le detruire après.
    Le fait de faire un "new" à chaque iteration, fait que vous abandonnez la reference de votre ancien objet "Image" pour en cree un nouveau, ce qui réalloue de la mémoire. Vous pouvez, à la place, faire un "FromFile()"
    Ca marche pas comme ça : FromFile est une méthode statique, et renvoie une nouvelle instance de Image. Avec ce code la variable MonImage n'est jamais assignée

  4. #4
    Membre averti
    Homme Profil pro
    Technicien Qualité Logiciel
    Inscrit en
    Janvier 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien Qualité Logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2010
    Messages : 44
    Par défaut
    Je vous remercie tous les deux.

    Donc je viens de tester et en effet la fonction .Dispose correspond bien à mon attente.
    Je pensais qu'elle servait à "Détruire" une variable (donc plus moyen de l'utiliser), car si on fait de même pour une TextBox par exemple, le composant est supprimé.

    Donc c'est nikel, je préfère faire cela, car même si le Garbage Collecteur passe ensuite, ça utilise de la mémoire pour rien entre temps...

    Je vous remercie encore.

    Bonne journée!

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par CryoCid Voir le message
    Donc je viens de tester et en effet la fonction .Dispose correspond bien à mon attente.
    Je pensais qu'elle servait à "Détruire" une variable (donc plus moyen de l'utiliser), car si on fait de même pour une TextBox par exemple, le composant est supprimé.
    "détruire une variable" n'a pas de sens : une variable est seulement une référence vers un objet. Ce que tu peux "détruire", c'est l'objet lui-même, pas la variable. Et ce n'est pas parce que tu détruis l'objet référencé par une variable que tu ne peux plus utiliser la variable (par contre tu ne peux plus utiliser l'objet)

  6. #6
    Membre averti
    Homme Profil pro
    Technicien Qualité Logiciel
    Inscrit en
    Janvier 2010
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien Qualité Logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2010
    Messages : 44
    Par défaut
    Ok tomlev, merci pour cette précision.
    Je me suis mal exprimé, mes excuses.

  7. #7
    Membre éprouvé Avatar de LeCygne
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2010
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2010
    Messages : 91
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Non, en l'occurrence ça sert à rien (pour une variable locale), parce la variable va sortir du scope à la fin de la méthode de toutes façons, et sera éligible pour le GC
    ....
    Ca marche pas comme ça : FromFile est une méthode statique, et renvoie une nouvelle instance de Image. Avec ce code la variable MonImage n'est jamais assignée
    C'est bien ce que je disais :

    Citation Envoyé par LeCygne Voir le message
    Je ne suis pas specialiste de la mémoire

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

Discussions similaires

  1. [C++/CLI] Libérer une variable du type cli::array
    Par ekinox17 dans le forum C++/CLI
    Réponses: 2
    Dernier message: 25/01/2006, 09h16
  2. [BES] Création d'une variable d'environnement
    Par NGI80 dans le forum Autres
    Réponses: 2
    Dernier message: 17/10/2002, 07h31
  3. Comparaison d'un registre 8 bits avec une variable 32 bits
    Par tupperware dans le forum x86 32-bits / 64-bits
    Réponses: 3
    Dernier message: 15/10/2002, 10h25
  4. Désigner une variable avec une variable?
    Par littleman dans le forum Paradox
    Réponses: 4
    Dernier message: 12/08/2002, 11h21
  5. Réponses: 4
    Dernier message: 05/06/2002, 14h35

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