Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1380 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  [.NET] Libérer de la mémoire sur des objets volumineux

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[.NET] Libérer de la mémoire sur des objets volumineux

n°1547374
naglafar
Posté le 23-04-2007 à 16:51:01  profilanswer
 

Bonjour,
 
Je suis en train de faire une reprise de données sur un catalogue et je dois notament passer d'un champ texte "image" à 2 champ dans la nouvelle base de données (SqlServer) de type image : un pour l'image, l'autre pour la miniature. Pour celà je dois donc ouvrir l'image a partir de son lien et ensuite l'enregistrer dans ma base de données.
 
Je fais déjà monImage.dispose(), maMiniature.dispose() et mon objet monProduit.dispose() qui contient toutes les propriétés et qui fait l'insert dans la base de données, mais malgrès ça, lorsque j'exécute et que je regarde les processus, la mémoire ne cesse d'augmenter jusqu'à saturation et message d'erreur "Mémoire insufisante".
 

Code :
  1. Public Function AjoutImage(ByVal oProduit As Dal.ClsTpProduit, ByVal oNomFichier As String, ByVal oCount As Int32) As Boolean
  2.         Dim oCheminFichier As String
  3.         Dim oFileInfo As IO.FileInfo
  4.         Dim oProduitImage As New Dal.ClsTpProduitImage(oNomFichier)
  5.         Dim oImage As Image
  6.         Dim oResult As Boolean
  7.         Dim oProduitColoris As Dal.ClsTpProduitColoris
  8.         'Mois et annee pour le dossier image'
  9.         Dim oMois As String = oProduit.CreeLe.Month.ToString("00" )
  10.         Dim oAnnee As String = oProduit.CreeLe.Year.ToString("0000" )
  11.         'Recherche de l image'
  12.         oCheminFichier = "Z:\ " & oAnnee & "\ " & oMois & "-" & oAnnee.Substring(2, 2) & "\ " & oNomFichier.Replace("jpg", "JPG" )
  13.         oFileInfo = New IO.FileInfo(oCheminFichier)
  14.         Try
  15.             'Propriétés de connection'
  16.             oProduitImage.Connection = oProduit.Connection
  17.             oProduitImage.Transaction = oProduit.Transaction
  18.             'Propriétés de lobjet image'
  19.             oProduitImage.ProduitUid = oProduit.ProduitUid
  20.             'Dates et modifieur'
  21.             oProduitImage.ModifieLe = oProduit.ModifieLe
  22.             oProduitImage.ModifieParUid = oProduit.ModifieParUid
  23.             oProduitImage.CreeLe = oProduit.CreeLe
  24.             oProduitImage.CreeParUid = oProduit.CreeParUid
  25.             If IO.File.Exists(oCheminFichier) Then
  26.                 Try       
  27.                     oProduitImage.Nom = oFileInfo.Name.Split("."c)(0)
  28.                     oProduitImage.Extension = oFileInfo.Extension.Replace(".", "" )
  29.                     oProduitImage.Numero = oCount
  30.                     'Création de l image et de la miniature'
  31.                     oProduitImage.Document = xCasaque.xIOCommon.GetByteByFile(oFileInfo.FullName)
  32.                     oImage = xCasaque.xImage.GetImageByByte(oProduitImage.Document, New Size(250, 250))
  33.                     oProduitImage.Miniature = xCasaque.xImage.GetByteByImage(oImage, oProduitImage.Extension)
  34.                     'Enregistrement de l image'
  35.                     oResult = oProduitImage.Save
  36.                     'Libération de l image'
  37.                     oImage.Dispose()
  38.                 Catch ex As Exception
  39.                     oResult = False
  40.                     Throw ex
  41.                 End Try
  42.             If Not oResult Then
  43.                 Exit Try
  44.             End If
  45.             'Enregistrement du Produitcoloris'
  46.             oProduitColoris = New Dal.ClsTpProduitColoris(oProduit.ProduitUid, Bll.MesValeursDefaut.CouleurNonSpecifieeUid)
  47.             'Propriétés de connection'
  48.             oProduitColoris.Connection = oProduit.Connection
  49.             oProduitColoris.Transaction = oProduit.Transaction
  50.             'Affectation des paramètres'
  51.             oProduitColoris.ProduitImageUid = oProduitImage.ProduitImageUid
  52.             oProduitColoris.Reference = oProduit.Reference
  53.             oProduitColoris.Motif = False
  54.             'Dates et modifieur'
  55.             oProduitColoris.ModifieLe = oProduit.ModifieLe
  56.             oProduitColoris.ModifieParUid = oProduit.ModifieParUid
  57.             oProduitColoris.CreeLe = oProduit.CreeLe
  58.             oProduitColoris.CreeParUid = oProduit.CreeParUid
  59.             'Enregistrement du produit coloris'
  60.             oResult = oProduitColoris.Save()
  61.             oProduitImage.Dispose()
  62.         Catch ex As Exception
  63.             oResult = False
  64.             Throw ex
  65.         End Try
  66.         Return oResult
  67.     End Function


 
Est-ce que quelqu'un a une idée pour m'aider à résoudre ce problème ?
 
Merci d'avance :hello:


Message édité par naglafar le 23-04-2007 à 17:57:42
mood
Publicité
Posté le 23-04-2007 à 16:51:01  profilanswer
 

n°1547656
moi23372
Posté le 23-04-2007 à 21:12:59  profilanswer
 

fait un collect afin de forcer le garbage collector de passer sur les objets

n°1547900
naglafar
Posté le 24-04-2007 à 10:56:40  profilanswer
 

Je me suis renseigné sur le GC.Collect, ça semble en effet être la bonne façon de faire pour libérer la mémoire, mais malheureusement ça ne change rien dans mon cas : dans mon exécution il passe dans le GC.Collect mais quand je regarde dans le gestionnaire des tâches, la mémoire ne cesse d'augmenter. Pourtant les objets volumineux appellent tous la fonction Dispose donc il devrait pouvoir me les vider :(

n°1547983
_Mose_
Lonesome coder
Posté le 24-04-2007 à 13:06:38  profilanswer
 

Je parle pas très bien VB et j'ai pas trop de temps pour analyser ton code, mais pour les objets à libérer :
* de manière générale vaut mieux faire un Dispose() et les mettre à null juste après.
 
Sinon ceux qu'il faut flinguer prioritairement :
* les images (comme tu l'as fait)
* tous les outils de GDI+  (Pen, Brush, Font)
* la connection à ta base de donnée
* les sql commandes
* les transactions
 
En l'occurence, très rapidement, essaye d'abord de mettre à null les objets que tu Dispose(), et dis-nous si ça résoud un peut tes pb.

n°1548628
Tamahome
⭐⭐⭐⭐⭐
Posté le 25-04-2007 à 13:30:38  profilanswer
 

moi23372 a écrit :

fait un collect afin de forcer le garbage collector de passer sur les objets


 
Très mauvaise idée. Le Collect effectue un parcours de la zone mémoire alloué à la CLR et la defrag en meme temps qu'elle libère des blocks de mémoire. C'est énormément chronophage (et niveau conso cpu, c'est pareil). D'une manière générale, il faut toujours laisser le système s'occuper de ce genre de chose, on est pas en C.
 
S'il a un memory leak, c'est qu'il y a un problème dans son code. Soigner le symptome n'est pas la solution. Il faut soigner la maladie.


---------------
Hobby eien /人◕ ‿‿ ◕人\
n°1548630
Tamahome
⭐⭐⭐⭐⭐
Posté le 25-04-2007 à 13:32:31  profilanswer
 

rapidement je peux deja dire que remplacer ses horribles concaténation de string par un stringbuilder lui améliorera la mémoire.
 
Edit : ce qui consomme le plus ce sont les "string" car c'est immutable et ce n'est jamais libéré par le garbage collector.

Message cité 1 fois
Message édité par Tamahome le 25-04-2007 à 13:33:31

---------------
Hobby eien /人◕ ‿‿ ◕人\
n°1548659
_Mose_
Lonesome coder
Posté le 25-04-2007 à 14:18:04  profilanswer
 

Tamahome a écrit :

rapidement je peux deja dire que remplacer ses horribles concaténation de string par un stringbuilder lui améliorera la mémoire.

Pas en .Net 2.0
Ca a été amélioré :)
 
Et sinon je suis à 100% d'accord avec toi sur le GC.Collect().

n°1548691
naglafar
Posté le 25-04-2007 à 15:46:44  profilanswer
 

Après plusieurs tests, j'i vu que GC.Collect() fonctionnait mais qu'il ne libérait que peu d'espace, il reste des objets très volumineux. J'ai changé le String en StringBuilder, ça a un peu diminué la mémoire mais pas encore assez. Ca atteint rapidement les 1 Go de mémoire utilisé donc ça ne peut pas être que sur des chaînes de caractères, il y a surement les images manipulées qui interviennent là dedans.
 
En fait je me demande si ça ne viendrait pas de ma table d'origine. Ma source c'est une DataTable assez grosse (8000 lignes) et qui contient aussi des images et je boucle avec un For oI = 0 To oDataTable.Count - 1 dedans. Seulement ce qui est étonnant c'est que je la charge intégralement dès le début de la migration et que ensuite je ne sais que l'exploiter, donc sa taille ne devrait pas augmenter.

n°1548747
pikti
I’ve done worse
Posté le 25-04-2007 à 17:17:27  profilanswer
 

tu peux essayer  
- d'implémenter IDisposable dans tes objets et du coup de faire des using pour les objets créés dans cette méthode, et probablement dans la méthode qui appelle celle-ci sûrement en boucle,
- passer tes arguments par référence
 
 
edit : un très bon lien sur le GC (et les using, IDisposable, WeakReference..)
 
http://www.dotnetguru.org/articles/GC/GC.html


Message édité par pikti le 26-04-2007 à 09:48:44
n°1549101
Tamahome
⭐⭐⭐⭐⭐
Posté le 26-04-2007 à 07:28:12  profilanswer
 

naglafar a écrit :

Après plusieurs tests, j'i vu que GC.Collect() fonctionnait mais qu'il ne libérait que peu d'espace, il reste des objets très volumineux. J'ai changé le String en StringBuilder, ça a un peu diminué la mémoire mais pas encore assez. Ca atteint rapidement les 1 Go de mémoire utilisé donc ça ne peut pas être que sur des chaînes de caractères, il y a surement les images manipulées qui interviennent là dedans.
 
En fait je me demande si ça ne viendrait pas de ma table d'origine. Ma source c'est une DataTable assez grosse (8000 lignes) et qui contient aussi des images et je boucle avec un For oI = 0 To oDataTable.Count - 1 dedans. Seulement ce qui est étonnant c'est que je la charge intégralement dès le début de la migration et que ensuite je ne sais que l'exploiter, donc sa taille ne devrait pas augmenter.


 
Essaye en ne chargeant que la ligne dont tu as besoin. Utilise des using{} a la place des dispose, c'est plus pratique (ca appelle automatiquement le dispose. Sinon faut mettre les dispose() dans un finaly dans tes blocs try/catch pour etre sur que ce soit appellé...).  
 
T'as posté l'intégralité du code au fait ? Si je le prends, ca compile ? (j'ai pas essayé)
 
Edit : ah merde c'est du vb.net [:skeye]


Message édité par Tamahome le 26-04-2007 à 07:28:40

---------------
Hobby eien /人◕ ‿‿ ◕人\
mood
Publicité
Posté le 26-04-2007 à 07:28:12  profilanswer
 

n°1550124
naglafar
Posté le 26-04-2007 à 16:16:00  profilanswer
 

Merci beaucoup pour votre aide. J'ai trouvé d'où vient le problème mais vous ne pouviez pas le voir...
 
en fait c'est ma fonction qui génère la miniature de l'image qui ne libère pas bien la mémoire
 
oImage = xCasaque.xImage.GetImageByByte(oProduitImage.Document, New Size(250, 250))
oProduitImage.Miniature = xCasaque.xImage.GetByteByImage(oImage, oProduitImage.Extension)
 
J'ai pas encore cherché à quel endroit il y a un objet qui n'a pas été libéré mais maintenant que je sais d'où ça vient ça devrait être plus facile.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  [.NET] Libérer de la mémoire sur des objets volumineux

 

Sujets relatifs
[.Net - VSTO] Problème de tableaux dans word[Résolu][C# .Net] Changer le curseur quand je pointe une image
Qules objets sont dragables ?[RESOLU][ASP.NET][C#]Comment modifier les entetes d'un DataGrid?
[IIS / ASP.NET]Logiciel de detection de fuite mémoire
destruction en règle d'un objet perso en .NETProjet d'installation .NET qui requiert install externe
ASP.NET structure table datasetProblème de thread avec les sockets en .NET
Plus de sujets relatifs à : [.NET] Libérer de la mémoire sur des objets volumineux


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR