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 :

Problème de ressources non libérées


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut Problème de ressources non libérées
    Bonjour,

    Étant lassé de voir toujours le même fond d'écran et n'ayant pas envie de le changer constamment manuellement, je me suis mis à la création d'une application faisant varier mon fond d'écran aléatoirement sur base de photo se trouvant dans un répertoire donné. Cette application est prévue pour WinXP (Win7 prévoyant déjà cette fonctionnalité pour les fonds d'écran)

    Mon programme fonctionne comme suit :
    1. l'utilisateur définit un répertoire source d'où l'application puisera les photos
    2. pour chaque photo, l'application l'ouvre dans une picturebox cachée, la redimensionne et la sauve dans un répertoire de travail pour ne pas utiliser directement les photos de l'utilisateur
    3. une fois la source de photo définie, l'utilisateur défini un interval de temps via un contrôle numericupdown
    4. l'utilisateur clique sur le bouton start ce qui lance le timer avec l'interval définit et qui, à chaque interval, fera varier l'écran de fond de windows


    Voici maintenant un peu de code (certains passages ont été repris de codes existants trouvés sur le net):
    point 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
        Private Sub DefineTheSourceFolderToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DefineTheSourceFolderToolStripMenuItem.Click
            If fbdSourcefolder.ShowDialog = Windows.Forms.DialogResult.OK Then
                sourceDir = fbdSourcefolder.SelectedPath
                For Each file As String In IO.Directory.GetFiles(WallpaperDir)
                    IO.File.Delete(file)
                Next
                Form1.InitializePictureBox()
                MessageBox.Show("Transfert and resizing pictures done")
            End If
        End Sub
    point 2
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
     
        Dim Sw, Sh As Integer
        Dim Pw1, Ph1, Pw2, Ph2 As Integer
        Dim newName As String = ""
     
        Public Sub InitializePictureBox()
            Sw = getScreenWidth()
            Sh = getScreenHeight()
     
            If Sw >= Sh Then
                ResizeEnFonctionDeH()
            Else
                ResizeEnFonctionDeW()
            End If
        End Sub
     
        Public Sub ResizeEnFonctionDeH()
     
            For Each filename As String In Directory.GetFiles(Main.sourceDir)
                'PictureBox1 doit etre posé sur le form
                'c genant de pouvoir voir le picturebox1, qui sert uniquement pour
                'qualculer le ration de l'image a transformer
                ' Set picturebox1 not visible 
                Me.PictureBox1.Visible = False
                ' Set the SizeMode property.
                Me.PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize
                PictureBox1.Image = System.Drawing.Image.FromFile(filename)
                'get W1 and H1 pour calculer le ratio
                Pw1 = Me.PictureBox1.Width
                Ph1 = Me.PictureBox1.Height
                'nouveau size pour picturebox2 (uniquement si la hauteur de la photo est plus grande que la hauteur de l'écran)
                If Ph1 > Sh Then
                    Ph2 = Sh
                    Pw2 = CInt(Math.Round(Ph2 * Pw1 / Ph1))
                Else
                    Ph2 = Ph1
                    Pw2 = Pw1
                End If
                'et maintenant la transformation : 
                ' Get the source bitmap.
                Dim bm_source As New Bitmap(Me.PictureBox1.Image)
                ' bitmap pour le resultat.
                Dim bm_dest As New Bitmap(Pw2, Ph2)
                '  Creer un GraphicsOject pour le resultat du Bitmap.
                Dim gr_dest As Graphics = Graphics.FromImage(bm_dest)
                ' Copy l'image source dans le bitmap.
                gr_dest.DrawImage(bm_source, 0, 0, Pw2, Ph2)
                ' Display result in picturebox2.
                ' Picturebox2 contient l'image transformé et avec le meme ratio
                'location of Picturebox2
                Me.PictureBox2.Left = 5
                Me.PictureBox2.Top = 5
                'stretch ne deforme pas l'image ici parceque le ration a ete calculé
                Me.PictureBox2.SizeMode = PictureBoxSizeMode.StretchImage
                'Adjust size of picturebox2 to custome size
                Me.PictureBox2.Width = Pw2
                Me.PictureBox2.Height = Ph2
                Me.PictureBox2.Image = bm_dest
                ' sauvegarder l'image en jpg
                newName = Main.WallpaperDir & filename.Substring(filename.LastIndexOf("\"))
                Me.PictureBox2.Image.Save(newName, System.Drawing.Imaging.ImageFormat.Jpeg)
                'on peut auusi sauvegarder in gif, bmp etc.
                bm_source.Dispose()
                bm_dest.Dispose()
                gr_dest.Dispose()
                'GC.Collect()
            Next
        End Sub
     
        Public Sub ResizeEnFonctionDeW()
     
            For Each filename As String In Directory.GetFiles(Main.sourceDir)
                'PictureBox1 doit etre posé sur le form
                'c genant de pouvoir voir le picturebox1, qui sert uniquement pour
                'qualculer le ration de l'image a transformer
                ' Set picturebox1 not visible 
                Me.PictureBox1.Visible = False
                ' Set the SizeMode property.
                Me.PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize
                PictureBox1.Image = System.Drawing.Image.FromFile(filename)
                'get W1 and H1 pour calculer le ratio
                Pw1 = Me.PictureBox1.Width
                Ph1 = Me.PictureBox1.Height
                'nouveau size pour picturebox2 (uniquement si la largeur de la photo est plus grande que la largeur de l'écran)
                If Pw1 > Sw Then
                    Pw2 = Sw
                    Ph2 = CInt(Math.Round(Pw2 * Ph1 / Pw1))
                Else
                    Pw2 = Pw1
                    Ph2 = Ph1
                End If
                'et maintenant la transformation : 
                ' Get the source bitmap.
                Dim bm_source As New Bitmap(Me.PictureBox1.Image)
                ' bitmap pour le resultat.
                Dim bm_dest As New Bitmap(Pw2, Ph2)
                '  Creer un GraphicsOject pour le resultat du Bitmap.
                Dim gr_dest As Graphics = Graphics.FromImage(bm_dest)
                ' Copy l'image source dans le bitmap.
                gr_dest.DrawImage(bm_source, 0, 0, Pw2, Ph2)
                ' Display result in picturebox2.
                ' Picturebox2 contient l'image transformé et avec le meme ratio
                'location of Picturebox2
                Me.PictureBox2.Left = 5
                Me.PictureBox2.Top = 5
                'stretch ne deforme pas l'image ici parceque le ration a ete calculé
                Me.PictureBox2.SizeMode = PictureBoxSizeMode.StretchImage
                'Adjust size of picturebox2 to custome size
                Me.PictureBox2.Width = Pw2
                Me.PictureBox2.Height = Ph2
                Me.PictureBox2.Image = bm_dest
                ' sauvegarder l'image en jpg
                newName = Main.WallpaperDir & filename.Substring(filename.LastIndexOf("\"))
                Me.PictureBox2.Image.Save(newName, System.Drawing.Imaging.ImageFormat.Jpeg)
                'on peut auusi sauvegarder in gif, bmp etc.
                bm_source.Dispose()
                bm_dest.Dispose()
                gr_dest.Dispose()
                'GC.Collect()
            Next
        End Sub
    point 3 et 4
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
        Private Const SPI_SETDESKWALLPAPER As Integer = &H14
        Private Const SPIF_UPDATEINIFILE As Integer = &H1
        Private Const SPIF_SENDWININICHANGE As Integer = &H2
        Public WallpaperDir As String = Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\") + 1) & "Wallpaper"
        Public sourceDir As String = ""
        Dim images As New ArrayList
        Dim randomNumber As New Random
        Dim newNumber, oldNumber As Integer
     
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
            For Each image As String In IO.Directory.GetFiles(WallpaperDir)
                images.Add(image)
            Next
            Randomize()
            timer.Interval = nudInterval.Value * 1000
            timer.Enabled = True
        End Sub
     
        Private Sub Timer1_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles timer.Elapsed
            bgwWallPaper.RunWorkerAsync()
        End Sub
     
        Private Sub bgwWallPaper_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwWallPaper.DoWork
            Dim sfilename As String
            oldNumber = newNumber
            newNumber = randomNumber.Next(images.Count)
            While oldNumber = newNumber
                newNumber = randomNumber.Next(images.Count)
            End While
            sfilename = images(newNumber).ToString
            SetWallpaper(Image.FromFile(sfilename))
        End Sub
     
        Private Declare Auto Function SystemParametersInfo Lib "user32.dll" ( _
            ByVal uAction As Integer, ByVal uParam As Integer, _
            ByVal lpvParam As String, ByVal fuWinIni As Integer) As Integer
     
        ' change this to whatever filename you want to use
        Const WallpaperFile As String = "MovieCollectionImage.bmp"
     
        ''' <SUMMARY>
        ''' Sets the background of your Windows desktop.  
        ''' The image will be saved in MyPictures and the background 
        ''' wallpaper updated.
        ''' </SUMMARY>
        ''' The image to be set as the background.
        ''' <REMARKS></REMARKS>
        Friend Sub SetWallpaper(ByVal img As Image)
            Dim imageLocation As String
            imageLocation = My.Computer.FileSystem.CombinePath( _
                My.Computer.FileSystem.SpecialDirectories.MyPictures, WallpaperFile)
            Try
                img.Save(imageLocation, System.Drawing.Imaging.ImageFormat.Bmp)
                SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imageLocation, _
                    SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE)
            Catch Ex As Exception
                MsgBox("There was an error setting the wallpaper: " & Ex.Message)
            End Try
        End Sub
    Le plus gros problème se situe au niveau du point 2. Si le répertoire désigné par l'utilisateur contient un nombre trop important de photo, il en résultera une erreur dont le message est "Out of memory". Effectivement, lorsque je regarde les infos du process dans le gestionnaire des tâches, la mémoire utilisée augmente très vite et sans jamais redescendre. J'ai pourtant ajouté un appel à la méthode Dispose pour chaque new qui est fait précédent dans l'application mais rien n'y fait. J'ai également tenté de faire appel au GarbageCollector mais cela ne change rien non plus.

    J'avoue que c'est un des aspects de la programmation qui reste encore très flou pour moi. Je n'ai jamais eu aucune formation sur ce qui concerne la gestion des ressources et le peu que j'en sais, je l'ai appris en parcourant ce forum et manifestement, ce n'est pas suffisant.

    Bref, pouvez-vous m'aider à ce sujet ?

    Merci d'avance.

    Griftou.

  2. #2
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Re bonjour,

    Entre temps, j'ai continué mes recherches et j'ai continué à analyser mon code.
    J'ai appris qu'ajouter une assignation à Nothing pouvait également aider.

    J'ai donc ajouter cela. Ensuite j'ai constaté que je ne libérais pas les images au sein même des picturebox. J'ai donc ajouté cela et maintenant, je constate dans le gestionnaire des tâches que la mémoire utilisée ne s'envole plus mais reste constante.

    Je pensais donc avoir résolu mon problème mais en testant avec un nombre important d'images, 107 pour être précis (ce qui n'est finalement pas si grand que ça), j'arrive quand même à un out of memory alors que pourtant, si je vérifie dans le répertoire où l'application sauve les images redimensionnées, les 107 y sont bien présentes.

    Le out of memory se produit sur la ligne 27 du code du point 2 de mon message précédent.

    Je ne comprends donc absolument plus d'où vient ce out of memory étant donné que la mémoire utilisée reste relativement stable selon le gestionnaire des tâches.

    Please help !

    Griftou.

  3. #3
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Re bonjour à nouveau.

    J'ai trouvé la cause de ce out of memory.

    Il vient du fait que winxp (j'ignore si ce le cas pour d'autres versions) ajoute automatiquement dans les répertoires d'images un fichier nommé "Thumbs.db". Mon application essayait de traiter ce fichier comme si c'était une image (je n'ai pas encore gérer les cas où le dossier contient d'autre fichier) et c'est cela qui provoquait un out of memory.

    Je note donc cette discussion comme résolue puis que la réponse à la libération de la mémoire a été trouvé dans le 2e message.

    Griftou.

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

Discussions similaires

  1. Probleme de ressource non libérée - Image en WPF
    Par WhyNottt dans le forum Windows Presentation Foundation
    Réponses: 2
    Dernier message: 13/08/2010, 15h50
  2. problème ressource non trouvée
    Par likoudA dans le forum Wildfly/JBoss
    Réponses: 0
    Dernier message: 16/05/2010, 22h52
  3. Un erreur non gérée : problème de ressources
    Par Hemophilius dans le forum C++/CLI
    Réponses: 6
    Dernier message: 19/09/2008, 21h22
  4. Problème ressource non disponible
    Par tomy29 dans le forum JSF
    Réponses: 2
    Dernier message: 20/07/2008, 16h00
  5. problème de connexions non libérées
    Par niten dans le forum Hibernate
    Réponses: 4
    Dernier message: 22/08/2006, 15h53

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