12. oktober 2010 - 11:35Der er
9 kommentarer og 2 løsninger
Image.FromFile / Image.FromStream giver OutOfMemoryException
Jeg har fundet en masse om dette problem ved at google lige præcis min overskrift, men de aller fleste tilfælde er i relation til at man forsøger at loade meget store filer eller korrupte/tomme filer. Det er dog IKKE tilfældet for mig, derfor forsøger jeg lige at høre om der er nogen der kan give en løsning her.
I min kode indlæser jeg alle .jpg filer i en valgt mappe. Disse bliver gemt i et objekt og derefter i en generic list (samt en listbox). På et eller andet tidspunkt kan den ikke mere og smider en OutOfMemoryException.
foreach (string f in folderFiles) { try { fs = new FileStream(f, FileMode.Open, FileAccess.Read); img = Image.FromStream(fs, true, true); } catch (OutOfMemoryException ex) { // Excepitonhandling }
GalleryImage newObj = new GalleryImage(f, img, info.CreationTime); galleryList.Add(newObj); listboxBilder.Items.Add(newObj); }
fs.Dispose(); } }
Jeg har forsøgt med forskellige mængder billeder og jeg kan i nogle tilfælde indlæse 409 billeder med en samlet størrelse på 64,5 mb (det 410.ende smider exception). Men jeg kan også indlæse 107 billeder (á 184 mb) eller 182 (á 117 mb) inden OutOfMemoryException bliver kastet.
Jeg når jo åbenbart en eller anden form for peak, men er der nogen måde jeg kan undgå dette og stadig bevare min funktionalitet??
Jeg har forsøgt at bruge img.dispose(), men så kan den ikke længere læse fra det Image objekt jeg har tilføjet galleryList når jeg senere forsøger at tilgå denne.
Jeg tror ikke det er en god ide at loade så mange billeder ind i memory på en gang. Du skal huske på, at de fleste billeder fylder meget mere i memory, end de gør på harddisken, da de er komprimeret på harddisken.
I memory fylder alle billeder ca det samme som et bitmap billede på disken.
Havde det ikke været en ide, bare at gemme på referencen til billedet i memory, og loade det ind i memory bare når det skal bruges?
Det kan selvfølgelig godt være... Jeg bruger listbox'en til at fremvise det enkelte billede i en picturebox, men jeg kan selvfølgelig bare loade billedet på nyt hver gang det skal vises i stedet for at gemme det i memory.
...men så får jeg jo bare samme problem hvis man viser mange billeder efter hinanden. For jeg kan jo ikke dispose billedet jeg lige har assignet til picturebox'en.
Det er selvfølgelig rigtigt at du ikke kan bruge objektet længere når du har disposet det.
Men så kunne du gøre noget helt andet.
Du kunne erstatte dit Image i galleryimage med en stream. Det fylder ikke så meget, og så kunne du oprette dit billede ud fra stream objektet.
F.eks. sådan her: public partial class Form1 : Form { List<GalleryImage> galleryList = new List<GalleryImage>(); public Form1() { InitializeComponent(); }
Er det fuldt størrelses billeder du viser i din listbox?
Hvis det er små billeder, kan du gemme en thumnail i memory, og ha en reference til det originale billede, i tilfælde det fulde billede skal bruges senere.
Jeg endte med at gemme kun filepath i galleryList og indlæse det på ny fra (GalleryImage)listboxBilder.SelectedItem. Men når jeg så disband'er det forrige billedet inden jeg indlæser et nyt giver det ingen overhead.
Jeg vurderer I begge to gav mig den pegepind jeg behøvede, så smid lige et svar aaberg_cc... Så får I halvdelen hver.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.