hallo ich habe gesehen das dieses thema schon einige male diskutiert wurde
aber habe in keinem der theads eine wirkliche lösung gefunden.
und die msdn sagt ja auch
"Es ist nicht zulässig, das Bild in derselben Datei zu speichern, aus der es erstellt wurde. Dadurch wird eine Ausnahme ausgelöst."
gibt es wirlich keine möglichkeit eine bmp zu überschreiben?
oder ein workaround?
habe schon alles probiert was in den vorherigen theads vorgeschlagen wurde: von bmp.dispose() oder bmp=null oder gc.Collect()
oder streams oder file.delete();
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Hallo demondriver235,
was auf jeden Fall gehen sollte ist, das Bitmap-Objekt zu klonen, des Original zu entsorgen (Dispose) und dann den Klone zu speichern.
herbivore
ich habe clone zwar noch nicht probiert aber dispose killt das object nich wirklich
das auf das file auch nach dispose, = null und gc.collect noch ein process zugreift??
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Hallo demondriver235,
Dispose des Bitmap-Objekts sollte die zugehörige Datei schließen.
herbivore
davon bin ich eigendlich aus ausgegangen
ich habe deshalb um zu prüfen ob die datei freigegeben ist nach dispose
file.delete(file) probiert dann krieg ich einen IO error da die datei von einem anderen prozess verwendet wird??-
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Hallo demondriver235,
zeig mal den Code, mit dem du das BitmapObjekt erzeugst.
herbivore
public static string[] CollectImgFilesInFolder(string folder)
{
//Fill array with files
string[] imgFileArray = Directory.GetFiles(folder, "*.bmp");
//Check out how to resize
foreach (string file in imgFileArray)
{
//Load the bmp
Bitmap bmp = new Bitmap(file);
//get the original size
int originalHeight = bmp.Height;
int originalWidth = bmp.Width;
//
//if the height is bigger then the width
//
if (originalHeight > originalWidth)
{
//calculate new width
int newWidth = originalWidth / (originalHeight / 150);
//Create new size
Size newSize = new Size(newWidth, 150);
//Set new size on new bitmap
Bitmap newBmp = new Bitmap(bmp, newSize);
bmp.Dispose();
//Del the old one
File.Delete(file);
//save bmp
newBmp.Save(file);
}
//....
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Hallo demondriver235,
und das geht nicht? Bist du sicher die Datei nicht anderweitig geöffnet zu haben?
Bau mal bitte testweise ein Thread.Sleep zwischen Dispose und Delete ein.
herbivore
ich hab thread.sleep(0) gemacht, das sollte reichen oder?
dabei fliegt er auch wieder auf die fresse, gleicher fehler ...used by another process
das bild liegt zwar auf einem button der in einem panel liegt aber selbst da mach ich vorher ein panel.controls.clear bevor der code von ober ausgeführt wird und sonst mach e ich nichts mit der datei
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Hallo demondriver235,
liegt auf dem Panel dasselbe Bitmap-Objekt? Oder eins, dass unabhängig mit new Bitmap(file) erzeugt wurde? Wenn ja, reicht Clear da nicht, sondern es muss auch ein Dispose her.
herbivore
leider nicht die bmp's liegen wirklich nur auf den buttons hab trotzem panel.dispose mal eingebaut gleiches problem !?
übrigens: wenn ich das file.delete(file) weglasse
bekomme ich A generic error occurred in GDI+. was eigendlich wohl auch ein IO error
sein dürfte oder?
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Hallo demondriver235,
ich meinte Bitmap.Dispose.
Ich denke, dein Code oben müsste für sich alleine funktionieren.
herbivore
meinst du button.image.dispose()?
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Das Problem ist mir auch etwas rätselhaft.
Jedoch habe ich bim Durchsehen deines Codes folgendes gefunden:
//calculate new width
int newWidth = originalWidth / (originalHeight / 150);
Diese doppelte Division ist ... zumindest ungünstig.
Besser ist folgendes:
//calculate new width
int newWidth = (originalWidth * 150 ) / originalHeight;
@ borg da hast du zwar recht aber das ganze funktioniert ja bei ich einen anderen pfad zum speichern angebe als den von dem ich geladen habe
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
???
Deine Antwort ist mir jetzt ehrlich gesagt etwas rätselhaft.
Was hat denn der Pfad mit der Berechnung zu tun?
nichts, deshalb sag ich ja das du im bezug auf die berechnung recht hast aber das mein problem nicht löst
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Ok, dann habe ich das nur falsch verstanden.
Dein Code an sich funktioniert auf jeden Fall. Hat bei mir ganz brav ein Verzeichnis mit Bildern konvertiert.
Daher kann es nur an dem Button liegen. Eventuell reicht schon ein Button.Dispose?
bei dir läuft das ? oh man ich weiss echt nicht mehr was ich machen soll
ich hab die buttons zur laufzeit erstellt
//Create a button object for each labFile
for (int i = 0; i < labFileArray.Length; i++)
{
Button btn = new Button();
//Set the properties
btn.Location = new System.Drawing.Point(200, 40 + i * 200);
btn.Name = "button" + i.ToString(); ;
btn.Size = new System.Drawing.Size(150, 150);
btn.Text = labFileArray[i].ToString();
btn.UseVisualStyleBackColor = true;
btn.BackColor = Color.White;
//Add an Eventhandler
btn.Click += new System.EventHandler(btn_Click);
//If an img file for the label exists put it on the button
for (int j = 0; j < imgFileArray.Length; j++)
{
//a little string formating for filename comparison
string labelFileName = labFileArray[i].ToString().ToUpper().Replace(".LAB", "");
string imageFileName = imgFileArray[j].ToString().ToUpper().Replace(".BMP", "");
//Set the image if found
if (labelFileName == imageFileName)
{
btn.Image = System.Drawing.Image.FromFile(imageFileName + ".BMP");
}
}
//Finally add each button to the flowLayoutPanel
this.flowLayoutPanelLabels.Controls.Add(btn);
deswegen kann ich nur die controls im panel disposen
siehe:
int buttonCount = this.flowLayoutPanelLabels.Controls.Count;
for (int i = 0; i < buttonCount; i++)
{
this.flowLayoutPanelLabels.Controls[i].Dispose();
}
aber das müsste doch ausreichen?
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Eigentlich sollte das schon reichen. Auch wenn du die for-Schleife durch eine foreach-Schleife ersetzen kannst.
Wann wird denn die "Dispose-Schleife" aufgerufen?
Ist sichergestellt, dass sie vor dem Konvertieren aufgerufen wird?
das ist sichergestellt
aber die schleife muss so heissen (im post hatte ich das buttonCount-- vergessen)
int buttonCount = this.flowLayoutPanelLabels.Controls.Count;
for (int i = 0; i <= buttonCount; i++)
{
this.flowLayoutPanelLabels.Controls[i].Dispose();
buttonCount--;
}
ich hab wirklich keine ahnung warum das nicht funzt!!!
aber schon mal vielen dank, das ihr euch damit auseinandersetzt!!
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Stimmt, mein Fehler.
Schon mal mit einem simplen
this.flowLayoutPanelLabels.Controls.Dispose() probiert?
jo! ...ich glaub ich hab mittlerweile schon alles disposed!
auch glaub ich mach mal feierabend, mir n bier auf und probier morgen weiter
euch ein schönes wochenende! falls ich die lösung finde poste ich die
falls ihr noch ne idee habt, bin für alles dankbar
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Hast du die Schleife mal debuggt?
Ich glaube nämlich nicht, dass durch Controls[n].Dispose() auch das Control aus der Collection gelöscht wird.
Da du aber ButtonCount dekrementierst, würdest du in diesem Fall nicht alle Controls erreichen.
Ansonsten alles ohne ButtonCount und am Ende einfach Controls.Clear()
das steht bei mir im code unter der schleife.
//Clear the panel
this.flowLayoutPanelLabels.Controls.Clear();
und die anzahl buttons muss ich ja dekrementieren
weil ich ja mit control_ dispose das control entferne und somit auch die anzahl der controls im panel verringer
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Eben das bezwifele ich ja.
Controls speichert Referenzen auf Objekte vom Typ Control.
Controls[n] liefert dir jetzt die Referenz auf ein Control.
Controls[n].Dispose() würde also die Dispose()-Methode des referenzierten Controls aufrufen, jedoch nichts an der Speicherung der Referenz in Controls ändern.
Hast du dieses Verhalten mal untersucht oder liege ich jetzt falsch?
Habe noch mal in der MSDN nachgelesen. Das Verhalten, dass du beschreibst trifft auf Controls.Remove() zu.
Bei Clear() steht:
Calling the Clear method does not remove control handles from memory. You must explicitly call the Dispose method to avoid memory leaks.
Daher gehe ich davon aus, dass das auch auf Remove() und RemoveAt() zutrifft.
Somit würde ich mal diese Schleife probieren:
while (this.flowLayoutPanelLabels.Controls.Count > 0)
{
this.flowLayoutPanelLabels.Controls[0].Dispose();
this.flowLayoutPanelLabels.Controls.RemoveAt( 0 );
}
ich glaub ich werde verrückt
hab gerade im prinzip das gleich gemacht wie du (ok deins ist eleganter, aber war ja auch nur test)
!!!!!!!und es funzt
int buttonCount = this.flowLayoutPanelLabels.Controls.Count;
for (int i = 0; i < buttonCount; i++)
{
this.flowLayoutPanelLabels.Controls[i].Dispose();
buttonCount = this.flowLayoutPanelLabels.Controls.Count;
i = 0;
}
this.flowLayoutPanelLabels.Controls[0].Dispose();
//for debugging to check control count ==0
int buttonCount2 = this.flowLayoutPanelLabels.Controls.Count;
du hattest recht und ich hab nicht alle controls erwischt
daran hats gelegen!
du bist mein kumpel, vielen dank , have a nice weekend
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Oder alternativ so:
foreach( Control LöschMich in this.flowLayoutPanelLabels.Controls)
{
LöschMich.Dispose();
}
this.flowLayoutPanelLabels.Controls.Clear();
Sollte prinzipiell keinen Unterschied machen, ausser dass diese Version möglicherweise etwas schneller ist.
Ok, kam zu spät.
Freut mich trotzdem, dass es jetzt hinhaut.
Dir auch schönes WE.
Hallo
ich habe ein ähnliches Problem, und bringe die Datei einfach nicht zu löschen.
bei Load wird eine PictureBox so mit einem Bild gefüllt:
Bitmap bild = new Bitmap(speicherpfad + fileName);
//SC: Artikelbild der PictrureBox zuweisen
this.PictureBild.Image = bild;
und wenn ich das per button event wieder löschen möchte bringt er mir den fehler... used by another prozess.
ich wollte es so löschen.
//SC: Bild löschen
PictureBild.Dispose();
File.Delete(speicherpfad + fileName);
kann mir da jemand helfen?
grüsse
Probier mal so:
// zuweisen
this.PictureBild.Image = new Bitmap(speicherpfad + fileName);
// löschen
this.PictureBild.Image.Dispose();
this.PictureBild.Dispose();
File.Delete(speicherpfad + fileName);
Funktioniert es jetzt?
Hej Borg
es geht leider nicht. kommt genau die gleiche Meldung, dass es noch woanders verwendet wird.
grüsse
edit://
es geht jetzt, musste noch in einer andern Form ein Dispose machen.