|
You last visited: Today at 13:14
Advertisement
[C#]Bitmap.Clone nicht genügend RAM
Discussion on [C#]Bitmap.Clone nicht genügend RAM within the .NET Languages forum part of the Coders Den category.
12/22/2014, 12:41
|
#1
|
elite*gold: 0
Join Date: Aug 2010
Posts: 880
Received Thanks: 113
|
[C#]Bitmap.Clone nicht genügend RAM
Hi,
ich hab ein Problem mit meinem Code, da die Exception ausgibt "Nicht genügend Arbeitsspeicher".
Ich wollte mir einen Screenshot vom Bildschirm machen und den Screenshot wieder in einzelne Blöcke aufteilen.
Dafür habe ich mir Pictureboxen dynamisch erstellt. Alle klappt super bis ich die Koordinaten von "Rectangle cloneRect = new Rectangle(iPointXPic, 0, 40, 25);" mit Int angebe. Also mit "iPointXPic" dann kommt die Meldung.
PHP Code:
Bitmap bmpScreenshot = new Bitmap(640, 320, PixelFormat.Format32bppArgb);
Graphics gfxScreenshot = Graphics.FromImage(bmpScreenshot); gfxScreenshot.CopyFromScreen(180, 370, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
pbAnalyseBild.Image = bmpScreenshot; int iIndex = 0;
int iPointXPB = 650; int iPointYPB = 30;
int iPointYPic = 0; int iPointXPic = 0;
PictureBox[] pbPictureBox = new PictureBox[50];
for (int i = 0; i < 5; i++) {
for (int k = 0; k < 10; k++) {
Rectangle cloneRect = new Rectangle(iPointXPic, 0, 40, 25); System.Drawing.Imaging.PixelFormat format = bmpScreenshot.PixelFormat; Bitmap cloneBitmap = bmpScreenshot.Clone(cloneRect, format);
pbPictureBox[iIndex] = new PictureBox(); pbPictureBox[iIndex].Location = new Point(iPointXPB, iPointYPB); pbPictureBox[iIndex].Name = "pic" + iIndex; pbPictureBox[iIndex].Size = new Size(40, 25); pbPictureBox[iIndex].Image = cloneBitmap; this.Controls.Add(pbPictureBox[iIndex]);
iPointYPB += 30; iPointXPic += 30;
iIndex++; }
iPointXPB += 50; iPointYPB = 30; }
Kann mir einer sagen woran das liegt?
So sieht es mit "Rectangle cloneRect = new Rectangle(0, 0, 40, 25);" aus.
Edit:
MfG Ludder231
|
|
|
12/22/2014, 14:53
|
#2
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Du reservierst Speicher und gibst ihn danach nie wieder frei. Irgendwann ist keiner mehr verfügbar.
Die Bitmap Klasse (und womöglich auch andere deiner verwendeten Klassen) implementieren das IDisposable Interface welches zuständig ist um die verwendeten Resourcen (und damit den reservierten Speicher) wieder freizugeben.
Das ist nicht Aufgabe der GC, diese ruft daher nicht automatisch die Dispose Methode auf, das musst du entweder selbst erledigen (Memberfunktion Dispose() aufrufen wenn du fertig bist und das Objekt zerstört werden kann) oder den using Block verwenden:
Das schon mal dazu - dein Problem hat aber eher damit zutun, das du erst gar nicht so viel Speicher reservieren kannst weil die Bilder zu viel verbrauchen. Wäre der Grund wieso es mit Koordinate 0 geht und mit einer beliebigen Größe nicht.
Wie viel Arbeitsspeicher hast du und wie viel ist in Benutzung gewesen bevor du dein Programm gestartet hast? Es wäre durchaus denkbar dass du durch den oben beschriebenen Fehler Speicherlücken erzeugt hast. Dann würde es mich nicht wundern wenn 95% des Arbeitsspeichers belegt sind obwohl du gar nichts in Benutzung hast was diese große Menge verursachen könnte.
|
|
|
12/22/2014, 15:12
|
#3
|
elite*gold: 0
Join Date: Aug 2010
Posts: 880
Received Thanks: 113
|
3,6GB von 8 sind belegt. Und wenn ich es starte dann auch. Dann kommt ja auch sofort der Fehler. Mir ist aufgefallen, dass die Exception aber von "Bitmap cloneBitmap = bmpScreenshot.Clone(cloneRect, format);" aufgerufen wird und nicht von "Rectangle cloneRect = new Rectangle(0, 0, 40, 25);" - dort ist mir das nur aufgefallen. Danke aber schon mal für die hilfe ich schau mal rüber.
Wenn ich die "Rectangle cloneRect = new Rectangle(0, 0, 40, 25);" X oder Y mit Hand eingebe funktioniert es....
|
|
|
12/22/2014, 15:19
|
#4
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Vielleicht gibt's einen Schutz der deine Anwendung auf *** MB Arbeitsspeicher limitiert?
Wenn die Exception bei Bitmap.Clone geworfen wird, ist es nun wirklich kein Wunder mehr. Mach's einfach so wie ich es erklärt habe und räume auf bevor du erneut klonst.
|
|
|
12/22/2014, 15:22
|
#5
|
elite*gold: 0
Join Date: Aug 2010
Posts: 880
Received Thanks: 113
|
Quote:
Originally Posted by Mostey
Vielleicht gibt's einen Schutz der deine Anwendung auf XXX MB Arbeitsspeicher limitiert?
Wenn die Exception bei Bitmap.Clone geworfen wird, ist es nun wirklich kein Wunder mehr. Mach's einfach so wie ich es erklärt habe und räume auf bevor du erneut klonst.
|
Also ich hab nach "this.Controls.Add(pbPictureBox[iIndex]);" dann "cloneBitmap.Dispose();" gemacht. Dann kam das ErrorImage von der PictureBox bei allen PB's. Wenn ich nun auch noch ne X oder Y Koordinate angebe, dann kommt immer noch die Meldung kein RAM.
Edit: Habs noch mal bisschen umgeschrieben.
PHP Code:
private void btnStart_Click(object sender, EventArgs e) {
Bitmap bmpScreenshot = new Bitmap(640, 320, PixelFormat.Format32bppArgb);
Graphics gfxScreenshot = Graphics.FromImage(bmpScreenshot); gfxScreenshot.CopyFromScreen(180, 370, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
pbAnalyseBild.Image = bmpScreenshot; int iIndex = 0;
int iPointXPB = 650; int iPointYPB = 30;
int iPointYPic = 0; int iPointXPic = 0;
PictureBox[] pbPictureBox = new PictureBox[100]; //x + 40 für clone //y + 30 für clone
//x = nach rechts //y = nach unten for (int i = 0; i < 2; i++) {
for (int k = 0; k < 8; k++) { //40; 25 Rectangle cloneRect = new Rectangle(iPointXPic, iPointYPic, 40, 25); System.Drawing.Imaging.PixelFormat format = bmpScreenshot.PixelFormat; Bitmap cloneBitmap = bmpScreenshot.Clone(cloneRect, format); pbPictureBox[iIndex] = new PictureBox(); pbPictureBox[iIndex].Location = new Point(iPointXPB, iPointYPB); pbPictureBox[iIndex].Name = "pic" + iIndex; pbPictureBox[iIndex].Size = new Size(40, 25); pbPictureBox[iIndex].Image = cloneBitmap; this.Controls.Add(pbPictureBox[iIndex]);
// cloneBitmap.Dispose();
//PB iPointXPB += 40; //Pic iPointXPic += 40;
iIndex++;
} //PB //wieder nach links rücken iPointXPB = 650; iPointYPB += 30;
}
}
Jetzt klappts mit z.b Reihe 1 x 10 Blöcke oder 2 x 8 Blöcke.
Auch das gewünschte Ergebnis. Nur noch das Problem mit dem RAM.
Außerdem kann ich doch gar nix disposen in der For-Schleife weil ich doch noch alles darin benötige. Erst wenn ich die ganzen Bilder in den Boxen aktualisieren möchte kann ich die alten disposen...
Könnte es an dem Pixelformat liegen? Das die 32bit pro pixel zu viel sind?
|
|
|
12/22/2014, 21:03
|
#6
|
elite*gold: 50
Join Date: Sep 2012
Posts: 3,841
Received Thanks: 1,462
|
Quote:
Originally Posted by Ludder231
Auch das gewünschte Ergebnis. Nur noch das Problem mit dem RAM.
Außerdem kann ich doch gar nix disposen in der For-Schleife weil ich doch noch alles darin benötige. Erst wenn ich die ganzen Bilder in den Boxen aktualisieren möchte kann ich die alten disposen...
Könnte es an dem Pixelformat liegen? Das die 32bit pro pixel zu viel sind?
|
Wenn du die PictureBox.Image aufrufst wird ein neues bild(eine kopie) erstellt also könntest du alles andere frei geben. Eine einfache lösung die gui ressourcen freizugeben die vom framework beim zeichnen benutzt worden sind ist:
Code:
Application.DoEvents();
this.Refresh();
(warum der code genau das verhalten zeigt kann ich nicht erklären ist mir aber auch egal solange es funktioniert)
Ich hatte mal ein ähnliches problem und bin damit zum ziel gekommen.
Außerdem muss du mal schauen ob alle parameter bei mehrmaligen aufrufen noch stimmen und ob CopyFromScreen nicht zufällig beim mehrmaligen aufrufen einfach nichts returned.
Du kannst dir aber auch einfach dir die gdi32.dll zu nutzen machen und das laden der bilder und die speicherverwaltung selber lösen.
EDIT: clonebitmap solltest du disposen oder global deklarieren
|
|
|
12/22/2014, 22:52
|
#7
|
elite*gold: 0
Join Date: Aug 2010
Posts: 880
Received Thanks: 113
|
Hat leider auch alles nicht geholfen. Check ich nicht. Der Ramverbrauch dieses Prozesses ist auch nur 13mb - 25mb.
Bin jetzt dazu übergegangen anstatt die Bildauschnitte zu clonen und wieder zu geben, nur die Farbe des Steins aus zu lesen. Das sieht auch gut aus soweit.
|
|
|
12/23/2014, 00:15
|
#8
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Quote:
Originally Posted by Ludder231
3,6GB von 8 sind belegt.
|
32 Bit oder 64 Bit? 32 Bit Betriebssysteme können maximal 4 GB (4096 MB) adressieren. Da das Betriebssystem ebenfalls Speicher benötigt, werden aus den 4096 vielleicht... 2 GB? Es sind hier also effektiv 2 GB frei die zwischen allen anderen Anwendungen geteilt werden.
Nebenbei lese ich gerade folgendes:
Quote:
|
You only have 2 GB available in 64-bit Windows, too. This is a limitation of the .NET Framework, not just of the 32-bit address space.
|
Da spielt es wohl auch keine große Rolle mehr ob du ein 64 Bit Betriebssystem hast oder nicht.
Quote:
Originally Posted by Ludder231
Check ich nicht. Der Ramverbrauch dieses Prozesses ist auch nur 13mb - 25mb.
|
Es geht nicht um den derzeitigen Verbrauch des Prozesses. Wenn du einmal Speicher für 500 Bilder reservierst (und das tust du mit der Bitmap Klasse), nimmst du dem Framework die Kontrolle über die Verwaltung weg. Bedeutet, wenn du den Speicher den du reserviert hast nicht mehr freigibst, wird er nicht freigegeben. Das ist (wie oben bereits erwähnt) nicht die Aufgabe der GC und das ist mit Absicht so implementiert.
Und ich garantiere dir dass bei diesem Code den du oben geposted hast sich dein Arbeitsspeicher wieder auf die selbe Anzahl füllen wird und du erneut eine OutOfMemory Exception gegen den Kopf geworfen bekommst.
Ich habe auch keine Lust mich nun noch ein zweites mal zu wiederholen. Wenn du dein Problem gelöst haben möchtest, schau dir an wie Speicher reserviert (und freigegeben) wird, was eine GC ist und was managed/unmanaged bedeutet.
|
|
|
12/23/2014, 00:47
|
#9
|
elite*gold: 50
Join Date: Sep 2012
Posts: 3,841
Received Thanks: 1,462
|
Quote:
Originally Posted by Ludder231
Hat leider auch alles nicht geholfen. Check ich nicht. Der Ramverbrauch dieses Prozesses ist auch nur 13mb - 25mb.
Bin jetzt dazu übergegangen anstatt die Bildauschnitte zu clonen und wieder zu geben, nur die Farbe des Steins aus zu lesen. Das sieht auch gut aus soweit.

|
deine vorgehensweise ist auch nicht so optimal. warum klonst du jedesmal aus einem hauptbild alle ressourcen und stellst diese dann in einer picturebox da auch wenn der gleiche bereich schon irgendwo geklont worden ist?
Ich meine du hast da ja immer wieder felder die gleich aussehen... die könntest du auch nur einmal einlesen.
Was hat leider auch nicht geholfen? ich wette du gibst den speicher immer noch nicht frei oder .net macht irgendeinen schwachsinn weil du mit den methoden irgendwas komisches anstellst
EDIT: Ich bin mir nicht sicher aber auch nur addressierter speicher dem kein wert zugewiesen wurde macht dem framework probleme
|
|
|
12/23/2014, 03:03
|
#10
|
elite*gold: 100
Join Date: Aug 2005
Posts: 595
Received Thanks: 208
|
1. Hör auf Mostey, selbst wenn das hier klappen wird, ist es absolut notwendig das du das Verständnis für den GC bekommst, ansonsten rennst du ein paar Stunden später in ein ähnliches Problem das sich nichtmehr lösen lässt.
2. Ohne es hier Checken zu können, mein Bauchgefühl sagt mir das du entweder dein Rechteck oder dein SourceBmp vermurkst hast und versuchsts entweder ein unendlich großen Ausschnitt zu kopieren oder der Source nicht wirklich da ist. Beides würde auch OutOfMemory schmeißen, wenn ich das nu noch richtig im Kopf habe.
|
|
|
12/23/2014, 12:52
|
#11
|
elite*gold: 0
Join Date: Aug 2010
Posts: 880
Received Thanks: 113
|
Okay. Danke für eure Antworten. Ich dachte das Problem lässt sich leicht lösen  . Nun werde ich dann wohl mal GC und den ganzen kram lernen müssen. Kann also geclosed werden
|
|
|
12/23/2014, 22:04
|
#12
|
elite*gold: 50
Join Date: Sep 2012
Posts: 3,841
Received Thanks: 1,462
|
Quote:
Originally Posted by Ludder231
Okay. Danke für eure Antworten. Ich dachte das Problem lässt sich leicht lösen  . Nun werde ich dann wohl mal GC und den ganzen kram lernen müssen. Kann also geclosed werden 
|
Da gibt es nicht viel zu wissen. Bei der drawing.dll musst du einfach nur alles disposen wo du nur kannst. wichtig ist auch das du nachdem du das bild der picture box geändert hast das eigentliche bild disposed.
Sollte das garnicht funktionieren kannst du auch selber die win32 funktionen importieren und selber alles machen. das hat bei mir geholfen als ich ein problem mit dieser dll hatte
|
|
|
12/29/2014, 16:27
|
#13
|
elite*gold: 67
Join Date: Aug 2014
Posts: 1,323
Received Thanks: 928
|
@Ludder231 ....
Add mich auf skype... die helfen dir ja nicht..
|
|
|
12/29/2014, 17:15
|
#14
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Quote:
Originally Posted by Xio.
@Ludder231 ....
Add mich auf skype... die helfen dir ja nicht..
|
Manchmal frag ich mich echt, wieso ich mich mit Problemen anderer beschäftige und so viel Zeit opfere wenn sowas zurückkommt.
Da geht es anderen genauso also halte dich mal etwas zurück. Es hat Gründe wieso wir ihm keinen Code geben den er nur kopieren braucht.
|
|
|
12/30/2014, 07:51
|
#15
|
elite*gold: 0
Join Date: Feb 2009
Posts: 1,137
Received Thanks: 573
|
Da der TE sein Problem gelöst hat, und es nicht hier gepostet hat wie, hier mal wie man das lösen könnte, falls noch andere das Problem haben.
Das Prinzip muss überarbeitet werden, man darf nicht so viele bitmaps gleichzeitig erstellen. hier mal meine Lösung mit nur einer Bitmap:
Code:
Bitmap Bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width / 4, Screen.PrimaryScreen.Bounds.Height / 4);
Graphics g = Graphics.FromImage(Bmp);
Size Faktor = new Size(Bmp.Width / 4, Bmp.Height / 4);
for (int i = 0; i < 16; i++) {
g.CopyFromScreen(new Point(Faktor.Width * (i % 4), Faktor.Height * (i / 4)), new Point(0, 0), Bmp.Size);
// Hier nun das was mit diesem Teil des Screens geschehen soll
} //Nächstes Part
g.Dispose();
Bmp.Dispose();
Das bietet die Gefahr, dass während des Vorganges der Screen sich verändern könnte, und daher die letzten Teile zu einem Anderen Gesamtbild als die ersten gehören. Wenn das wirklich stören sollte (mir fällt grade keine situation ein wann das von Nachteil sein könnte) der kann es mit 2 Bitmaps so machen
Code:
Bitmap Scr = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bo unds.Height);
Bitmap Bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width / 4, Screen.PrimaryScreen.Bounds.Height / 4);
Graphics g = Graphics.FromImage(Scr);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.PrimaryScreen.Bounds.Size);
g.Dispose();
g = Graphics.FromImage(Bmp);
Size Faktor = new Size(Bmp.Width / 4, Bmp.Height / 4);
for (int i = 0; i < 16; i++) {
g.DrawImage(Scr, new Rectangle(new Point(Faktor.Width * (i % 4), Faktor.Height * (i / 4)), Bmp.Size));
// Hier nun das was mit diesem Teil des Screens geschehen soll
}
g.Dispose();
Bmp.Dispose();
Scr.Dispose();
Jedes stück einzeln rausschneiden, bearbeiten (verschicken, abspeichern, whatever) und danach mit dem nächsten weitermachen
PS: Nicht getestet
|
|
|
 |
Similar Threads
|
Whatsappfehler: Nicht genügend Speicherplatz..
08/01/2014 - Technical Support - 4 Replies
Moin Leute,
ich habe seit letztens das Problem bei Whatsapp, das wenn ich Bilder schicken möchte, kommt die Meldung: "Nicht genügend Speicherplatz, versuchen sie es später erneut."
Weiß jemand, woran das liegt?
Danke im Vorraus
|
Nicht genügend Speicherplatz verfügbar!
09/01/2012 - Off Topic - 4 Replies
Hallo Leute,
jedesmal wenn mein Galaxy S3 versucht einige Apps zu Installieren nach dem Download, kriege ich immer diese Meldung "Nicht genügend Speicherplatz verfügbar"
Das komische daran ist das es nur bei einigen Apps so ist wie z.b Google Maps,Flipboard und Facebook
Intern ist noch 8GB Frei
und Extern ca 30Gb
Hoffe auf schnelle Hilfe
|
Nicht genügend Speicher..
05/05/2012 - Technical Support - 10 Replies
Hallo.
ich habe eine 40GB Fetsplatte.
Ich habe noch 7,1GB frei und will Call of Duty MW3 drauf machen.
Leider hat das spiel ca 15GB..
Ich habe schon allen scheiß runter gemacht etc.
Habe immer noch kein Speicher.
|
BF3 mp bekommt nicht genügend leistung
12/17/2011 - Battlefield - 3 Replies
also das problem ist das, dass ich jetzt irgendwie hinbekommen habe, dass mein singleplayer läuft nach 5 neuinstallationen oder so aber mein multiplayer startet immer noch nicht der prozess beendet sich immer wenn das spiel starten will und obwohl ich seine priorität schon ganz hoch gestellt habe bekommt er immer nur 100mb von meinem arbeitsspeicher aber schon alleine der singleplayer braucht bei mir 500mb um zu starten ich weiß einfach nicht woran das liegen könnte plugin ist installiert den...
|
Neu-->Bitmap geht nicht mehr [B]Elite*Gold
07/02/2011 - elite*gold Trading - 2 Replies
Hallo,
Ich habe ein großes, wirklich großes Problem:
Im Normalfall ist es so, dass wenn man Rechtsklick aufn Desktop macht, sich ein kleines Fenster öffnet und wenn man dann auf neu klickt, man sich eine neue .bmp Datei erstellen kann.
Bei mir ist es jetzt jedoch so, dass Bitmap in dieser Liste fehlt, obwohl alles andere, wie z.b. Textdokument, noch da ist.
Wer das problem löst, bekommt ein wenig E*Gold :)
|
All times are GMT +1. The time now is 13:16.
|
|