Libération mémoire

Résolu
cs_sansblog Messages postés 6 Date d'inscription samedi 24 décembre 2005 Statut Membre Dernière intervention 5 septembre 2006 - 27 août 2006 à 14:33
cs_sansblog Messages postés 6 Date d'inscription samedi 24 décembre 2005 Statut Membre Dernière intervention 5 septembre 2006 - 1 sept. 2006 à 09:47
Bonjour à tous.

J'ai écrit un programme qui entre autres affiche des images jpg.
Pour son option de tri, je ne peux renommer que les images que je n'ai pas visualisé, sinon j'obtiens un message d'erreur.(fichier en cours d'utilisation)
J'ai essayé de fermer le form en cours pour en ouvrir un autre -> le programme garde en mémoire les images ouvertes dans le form précédent -> message d'erreur.
D'ou ma question: comment libérer la mémoire de variables pour pouvoir renommer mes fichiers sans quitter le programme ?
Exemples de variables dont le contenu doit être "effacé de la mémoire":

 Public vignette(21) As String ' les 20 noms des 21 vignettes
 Public VignetteEnCours As String = "BOUTONS\noir.jpg"

ps : private au lieu de public ne règle pas mon pb; j'utilise public pour ne déclarer qu'une fois les variables accessibles pour différents modules.

7 réponses

Sicyons Messages postés 25 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 31 août 2006
29 août 2006 à 19:56
Pour info, fais attention car ces variables n'ont plus rien à voir avec d'autres langages que tu as peut-être connu comme VB6. En effet, ce sont des variables OBJET. Cela signifie qu'elles ne contiennent pas seulement une valeur mais toute une structure contenant à la fois variables (les fameuses "propriétés") et procédures (les "méthodes").

Donc quand tu fais :
ImageTemp = Image.FromFile(...)
MonPictureBox1.Image = ImageTemp
ImageTemp = Image.FromFile(...)
MonPictureBox2.Image = ImageTemp

Tu perds la référence au premier ImageTemp qui reste "dans la nature". Ce sera donc le cas pour TOUS tes autres ImageTemp sauf le dernier. Car ce ne sont pas seulement des valeurs que l'on peut remplacer comme cela. Dispose résoud une partie du problème mais ne libère pas toutes les ressources de ces objets.

Le deuxième problème est que lorsque le garbage collector (GC) de .NET nettoie automatiquement la mémoire de ton appli à sa fermeture, il ne sait pas ce qu'il doit libérer dans tes ImageTemp. Les objets Image sont complexes et dans ce cas ils ouvrent chacun un fichier. Je pense que le GC ne sait pas supprimer correctement de tels objets. Il faut manuellement appeller Dispose sur CHACUN. Tout du moins j'en ai déduit cela, et je pense que cela correspond à la réalité.

Voilà. J'espère t'avoir éclairé. J'espère faire prochainement un tutorial sur le sujet.

A plus.
3
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
27 août 2006 à 14:56
salut,
tu les affiches dans une picturebox ou une image....
avant de renommer :
picture1 (ou image1).picture=nothing
et ensuite ton code....

çà devrait suffir, éventuellement un DoEvents au pire.

++
PCPT  [AFCK]
<hr size="2" width="100%" />Prenez un instant pour répondre à ce sondage svp
0
cs_sansblog Messages postés 6 Date d'inscription samedi 24 décembre 2005 Statut Membre Dernière intervention 5 septembre 2006
27 août 2006 à 16:33
Merci pour l'aide mais ca ne marche pas.
J'afiche bien les images dans des picturebox.

Le Doevents, je ne sais pas l'utiliser: je n'ai trouvé que:
System.Windows.Forms.Application.DoEvents()
dans l'aide intégrée (vb.net2003 / visual studio 2003 sp1version découverte)

Le formulaire affichant les picturebox est fermé, un autre gère le tri des images et plante sur les fichiers jpg qui ont été visualisés, comme si le cache du programme conservait les noms des fichiers affichés !!!

Depuis l'exlporateur windows aussi je ne peux renommer ces fichiers jusqu'à ce que je quitte mon exécutable.
Si je ne visualise pas d'images, alors ma fonction "tri" renomme correctement les noms de fichiers .

Je crois que je dois passer par:
Object.Finalize,
méthode
  [Visual Basic]

mais je ne sais pas comment m'y prendre.
0
Sicyons Messages postés 25 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 31 août 2006
28 août 2006 à 16:01
Salut.

A ma connaissance, le DoEvents n'a rien à voir là-dedans (Il permet simplement de rendre temporairement la main à Windows pour qu'il puisse effectuer ses tâches courantes, pour les raffraîchissements de fenêtre, par exemple).

Private / Public ne servent qu'à indiquer la portée voulue pour tes variables (le module en cours (ou la méthode), l'Assembly en cours ou tout le monde).

Essaie cela :

Dim ImageTemp As Image 'Crée un objet Image en mémoire

ImageTemp = Image.FromFile(Chemin de ton fichier jpeg) 'Charge l'image
TonPictureBox.Image = ImageTemp 'Affiche l'image dans le PictureBox

Ca, c'est pour l'affichage de l'image.
Avant de fermer ton image, fait ceci :

TonPictureBox.Image = nothing 'Efface l'image du PictureBox
ImageTemp.Dispose() 'Restitue la mémoire de l'objet image
'et ferme le fichier associé.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_sansblog Messages postés 6 Date d'inscription samedi 24 décembre 2005 Statut Membre Dernière intervention 5 septembre 2006
29 août 2006 à 10:32
Merci et bravo [auteurdetail.aspx?ID=364146 Sicyons].

C'est bien l'instruction .Dispose() qui libère les fichiers images pour mon problème.

J'affiche environ 25 images /écran; j'ai du créer 25 variables ImageTemp1 à 25.
Car avec une seule variable d'attribution et des instructions
ImageTemp = Image.FromFile(Chemin image1)
MonPictureBox.Image1 = ImageTemp
Imagetemp.Dispose()
ImageTemp = Image.FromFile(Chemin image2)
MonPictureBox.Image2 = ImageTemp
etc. jus'qu'à 25, le form plante car Imagetemp.Dispose() efface les images 1 à 24 et le form plantait !!!

Maintenant je peux renommer mes fichiers images via mon programme pour réorganiser automatiquement ma base de données quand je le souhaite.

C'est bizarre que la réaffectation d'une variable ne libère pas l'objet mais c'est ainsi.
0
cs_sansblog Messages postés 6 Date d'inscription samedi 24 décembre 2005 Statut Membre Dernière intervention 5 septembre 2006
29 août 2006 à 21:13
Encore merci.
j'avais bien compris suite à ton 1er message.
C'est pourquoi j'ai du créer 25 nouvelles variables, que je "dispose" avant de leur affecter un nouveau contenu.
0
cs_sansblog Messages postés 6 Date d'inscription samedi 24 décembre 2005 Statut Membre Dernière intervention 5 septembre 2006
1 sept. 2006 à 09:47
J'ai un problème de libération de fichier similaire que je n'arrive pas à régler:
J'ouvre puis ferme un fichier x en lecture via Fileopen/ Fileclose.
Si j'ouvre ensuite un openfiledialog, j'ai une erreur : impossible de trouver le fichier x dans répertoire sélectionné.
Ma question est: comment libérer l'objet ouvert par fileopen ?

Détails:
je fais:
'Ouverture en mode lecture
Dim FichieIni as String
FichieIni="Basilette.ini
        FileOpen(1, FichieIni, OpenMode.Input, OpenAccess.Read)

        Do Until EOF(1)
            LignesBasiletteIni(i) = LineInput(1)
            i = i + 1 'soit i=i+1
        Loop
   Fileclose(1)
Bien entendu ca marche sauf que je ne peux pas renommer Basilette.ini: le fichier n'et pas libéré  par Fileclose(1)
Et si je fais
OpenFileDialogPochette.Dispose() ' sinon on peut pas réutiliser le fichier ouvert sans quitter l'application !!!
        OpenFileDialogPochette.Filter = "Images(*.jpg)|*.jpg"

        OpenFileDialogPochette.ShowDialog()
J'ai une erreur sur le fichier Basilette .ini ouvert plus haut.
D'ou ma question: comment libérer l'objet ouvert par fileopen ?
Remarquez que j'ai trouvé tout seul (en me basant sur l'aide de [auteurdetail.aspx?ID=364146 Sicyons]  (Imagetemp.Dispose)
)comment libérer l'objet openfiledialog pour lui attribuer un autre répertoire par défaut si on a ouvert un fichier dans un autre répertoire !
0
Rejoignez-nous