Har ett program som fakturerar kunder.
En gång per månad så faktureras några hundra kunder.
Programmet är skrivet i C# .NET 2.0 och det hämtar alla kunder ifrån databasen.
Kortfattat kan man säga att det görs så här:
//skapar en collection för varje användare
GenericCollection<User> usrColl = new GenericCollection<User>();
//loopar genom alla användare som ska faktureras
User usr = new User();
GenericCollection<ServiceItem> sItem = new GenericCollection<ServiceItem>();
//Loopar in allt som ska faktureras
usr.ServiceItem = sItem;
usrColl.Add(usr);
Det här i sig drar inte speciellt mycket minne, MEN när jag sen loopar igenom min User collection och skapar fakturorna och skriver ut/skickar PDF så börjar minnet ätas upp.
För varje User skapas 2 st bilder, som direkt efter att dom har använts körs Dispose på, även en byte[] som skapas sätts till null. Mitt PrintDocument körs Dispose på, i övrigt skapas inga direkta objekt som bör dra minne eller Dispose kan köras på.
När jag kör programmet och håller koll på det i aktivitetshanteraren så är minnesanvändningen väldigt låg, den ökar vid varje faktura för att sen när fakturan är klar, gå tillbaka till en låg minnes förbrukning. Men trots detta ökar växlingsfilen ganska kraftigt till att efter ett 40-tal fakturor slå i taket och jag får ett out of memory exception.
Jag kan inte i aktivitetshanteraren se vad som förbrukar så mycket minne.
Har ett program som fakturerar kunder.
En gång per månad så faktureras några hundra kunder.
Programmet är skrivet i C# .NET 2.0 och det hämtar alla kunder ifrån databasen.
Kortfattat kan man säga att det görs så här:
//skapar en collection för varje användare
GenericCollection<User> usrColl = new GenericCollection<User>();
//loopar genom alla användare som ska faktureras
User usr = new User();
GenericCollection<ServiceItem> sItem = new GenericCollection<ServiceItem>();
//Loopar in allt som ska faktureras
usr.ServiceItem = sItem;
usrColl.Add(usr);
Det här i sig drar inte speciellt mycket minne, MEN när jag sen loopar igenom min User collection och skapar fakturorna och skriver ut/skickar PDF så börjar minnet ätas upp.
För varje User skapas 2 st bilder, som direkt efter att dom har använts körs Dispose på, även en byte[] som skapas sätts till null. Mitt PrintDocument körs Dispose på, i övrigt skapas inga direkta objekt som bör dra minne eller Dispose kan köras på.
När jag kör programmet och håller koll på det i aktivitetshanteraren så är minnesanvändningen väldigt låg, den ökar vid varje faktura för att sen när fakturan är klar, gå tillbaka till en låg minnes förbrukning. Men trots detta ökar växlingsfilen ganska kraftigt till att efter ett 40-tal fakturor slå i taket och jag får ett out of memory exception.
Jag kan inte i aktivitetshanteraren se vad som förbrukar så mycket minne.
Vad gör man?
Svårt att säga varför minnet käkas upp utan någon mer inblick i exakt vad som görs men process Explorer från SysInternals kan ge dig rätt avancerad information om minnesanvändning av t.ex. en .NET-applikation.
Högerklicka på processen som kör faktureringarna och välj Properties. Där har du bl.a. en .NET-tab som kanske kan ge någon hint om vad som kan vara problemet.
Har hittat läckan och det är Printdokument:et.
Men jag lyckas inte förstöra graphics objektet efter varje faktura, har testat:
Graphics g = this.CreateGraphics();
g.Dispose();
men det hjälpte inte, var ska man helst placera disposen för printdocument?
Har hittat läckan och det är Printdokument:et.
Men jag lyckas inte förstöra graphics objektet efter varje faktura, har testat:
Graphics g = this.CreateGraphics();
g.Dispose();
men det hjälpte inte, var ska man helst placera disposen för printdocument?
Helst borde du inte ens köra CreateGraphics().
Använder du PrintPage-eventet på PrintDocument så får du med ett Graphics-objekt i PrintPageEventArgs.
Jag kör normalt inte CreateGraphics, men fick ett tips om att köra det för att direkt köra dispose på det.
Jag kör PagePrint, men där i bör jag väl knappast köra dispose?
Jag kör normalt inte CreateGraphics, men fick ett tips om att köra det för att direkt köra dispose på det.
Jag kör PagePrint, men där i bör jag väl knappast köra dispose?
Inte helt säker på vad du menar men om du plockar Graphicsobjektet från eventargs i PrintPage-eventet och ritar på det precis som vanligt. Om du använder det Graphicsobjektet så finns det ingen anledning till att köra dispose på det.
Sen kör du dispose på ditt PrintDocument när du är klar med utskriften så borde den släppa graphicsobjekt och annat.
Inte helt säker på vad du menar men om du plockar Graphicsobjektet från eventargs i PrintPage-eventet och ritar på det precis som vanligt. Om du använder det Graphicsobjektet så finns det ingen anledning till att köra dispose på det.
Jag körde det bara för att jag blev rekommenderad det, borttaget nu.
Phorpher skrev:
Sen kör du dispose på ditt PrintDocument när du är klar med utskriften så borde den släppa graphicsobjekt och annat.
Det gör jag men det släpper ändå inte resurserna.
Tänkte mer på om man skulle köra dispose så här:
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int x = e.MarginBounds.Left;
int y = e.MarginBounds.Top;
e.Graphics.DrawImage(img, x, y, e.MarginBounds.Width-45, e.MarginBounds.Height-30);
e.Graphics.Dispose();
}
Men det verkar funka, dock kan jag inte testa det i stor skala förren om en månad :e
Jag var rädd för att man skulle förstöra det grafiska objektet innan det kom till skrivaren, vilket skulle resultera i en tom utkrift men så var tydligen inte fallet.
Gjorde en liknande sak fast på Attachment:
Attachment attach = new Attachment( str );
message.Attachments.Add( attach );
attach.Dispose();
Vilket resulterade i att mailet aldrig gick iväg.
Du kan göra hur många Dispose() och sätta hur många objekt till NULL inget av det betyder att den frigör minne :)
Det enda det gör är att berätta för GC att om du behöver använda mer minne så kan du frigöra dessa objekt och så fall minska minnes förbrukningen, men så länge GC inte tycker att du använder för mycket minne så är det inte säkert att den städar upp efter dig, det betyder att du kan köra ditt program i en hel vecka utan att GC har tagit bort en byte data från minnet, eller att den ligger konstant varje sekund och försöker frigöra minne då det behövs bättre någon annanstans.
Du kan forsera GC att köra, men om den städar upp efter dig, är jag inte hundra på, jag har fått köra GC.Collect() två gånger eftervarandar fast jag gjort Dispose() på bilder, för att vara säker på att de verkligen har släppts från minnet. GC.Collect() är dock inget som man bör göra själv, utan det är upp till GC att sköta det, då den faktiskt har bättre koll på när det är bäst tidpunkt att göra en Collect() på.
Du kan göra hur många Dispose() och sätta hur många objekt till NULL inget av det betyder att den frigör minne :)
Det enda det gör är att berätta för GC att om du behöver använda mer minne så kan du frigöra dessa objekt och så fall minska minnes förbrukningen, men så länge GC inte tycker att du använder för mycket minne så är det inte säkert att den städar upp efter dig, det betyder att du kan köra ditt program i en hel vecka utan att GC har tagit bort en byte data från minnet, eller att den ligger konstant varje sekund och försöker frigöra minne då det behövs bättre någon annanstans.
Du kan forsera GC att köra, men om den städar upp efter dig, är jag inte hundra på, jag har fått köra GC.Collect() två gånger eftervarandar fast jag gjort Dispose() på bilder, för att vara säker på att de verkligen har släppts från minnet. GC.Collect() är dock inget som man bör göra själv, utan det är upp till GC att sköta det, då den faktiskt har bättre koll på när det är bäst tidpunkt att göra en Collect() på.
- M
Helt sant. Det man däremot kan fundera på är varför inte GCn när minnet faktiskt börjar bli fullt kör en uppstädningscykel. Windows skickar ett low memory notification när 32MB återstår och GCn ska reagera på den. Dock verkar det fungera si och så med det vad jag har förstått.