Laden...

[erledigt] Bitmaps bereithalten und anschließend anzeigen

Erstellt von dennisspohr vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.815 Views
dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren
[erledigt] Bitmaps bereithalten und anschließend anzeigen

Hallo,

ich schreibe momentan ein kleines Bildbearbeitungsprogramm. Dieses Programm kann mehrere Bilder in Stapeln verarbeiten.

Während man an den Einstellungen spielt, lassen sich Vorschauen generieren, sobald man auf eines der Originalfotos klickt.

Das Problem dabei: Jedes Mal, wenn Einstellungen geändert werden und das Vorschaubild aktualisiert werden muss, wird das Bild als Datei komplett neu geladen: sehr langsam.

Deshalb habe ich eine kleine Klasse geschrieben, die sich mehrere Fotos "merkt". Die Logik sollte sich hiermit erklären:


        public Bitmap GetImage(string path)
        {
            Bitmap returnImage = this.ImageCollection.GetImageByPath(path);

            if (returnImage == null)
            {
                if (this.ImageCollection.Count >= this.MaxImages)
                {
                    this.ImageCollection.DeleteImage(0);
                }

                returnImage = new Bitmap(path);
                this.ImageCollection.Add(new ImagePack(path, returnImage));
            }

            return returnImage;
        }

Nun das eigentliche Problem:
Wenn das Bild in der Liste vorhanden ist, wird dieses zurückgegeben. Wenn ich dieses zurückgegebene Bild auf der Form anzeigen will (darauf zugreifen will), wird eine Exception geschmissen:

"Ungültiger Parameter."

" bei System.Drawing.Image.get_Width()\r\n bei System.Drawing.Bitmap..ctor(Image original)\r\n bei DS.SimpleBorderCreator.WorkProcess.Worker_DoWork(Object sender, DoWorkEventArgs e) in D:\Visual Studio 2005\Projects\DS.SimpleBorderCreator\0.0.9.0\DS.SimpleBorderCreator\Classes\WorkProcess.cs:Zeile 233."

Wisst ihr, woran das liegt? Vielen Dank für eure Hilfe!

Gruß Dennis

20 Beiträge seit 2008
vor 15 Jahren

Wenn ich dieses zurückgegebene Bild auf der Form anzeigen will (darauf zugreifen will), wird eine Exception geschmissen

Dann schick bitte noch denn Quelltext wo das Bild angezeigt wird.

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo Console.Beep(),

Damit sollte es nichts zu tun haben:


this.previewPictureBox.Image = ImageLoader.GetImage(imgPath);

Gruß Dennis

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo,

vielleicht hilft euch dieser Scrennshot weiter.. Eventuell hattet ihr schonmal so etwas ähnliches:

Gruß Dennis

20 Beiträge seit 2008
vor 15 Jahren

Hm.. das ist wirklich merkwürdig.
Ich sehe da auch leider keinen Fehler in der Methode.

Tritt der Fehler generell auf oder nur wenn Einstellungen eines Bildes geändert wurden und das Vorschaubild aktualisiert werden muss?

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo Console.Beep(),

An den Einstellungen des Bildes wird nichts geändert.

Ablauf:

  • Das Bild wird geladen
  • Das Bild wird in einer Klasse gespeichert (Type: Bitmap)
  • Das Bild wird versucht anzuzeigen (das Bild aus der Klasse)

Gruß Dennis

20 Beiträge seit 2008
vor 15 Jahren

Ich vermute ,dass das Problem zwischen Laden und Ausgeben des Bildes zu finden ist. Es könnte sein das ein Fehler in der Datei ist aber dann hätte das Prog schon beim Laden dir die Exception ausgeworfen.

Es ist jedenfalls komisch das alle Daten in der Bitmap nicht funzen und die Exception auslösen. An irgendeiner Stelle geht warscheinlich die Bitmap kaputt.

Also nochmal debuggen und schaun ob diese Fehler wie im Bild von Anfang bis Ende da sind, wenn nicht hätten wir die stelle genau eingegrenzt.

(Bitte korrigiert mich wenn ich falsch liege)

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Was ich auf jeden Fall sagen kann: Die Bilder sind als Datei vollkommen in Ordnung.

Wenn die Abfrage

if (returnImage == null)

zutrifft, funktioniert das Laden des Bildes, da das Bild ja direkt in returnImage geladen und übergeben wird.

Der Fehler tritt nur auf, wenn das Bild aus der Collection geladen wird:

Bitmap returnImage = this.ImageCollection.GetImageByPath(path);

Gruß Dennis

2.760 Beiträge seit 2006
vor 15 Jahren

Benutzt du Threads? Wenn ja verhaust du dich evtl. mit denen und einem evtl. falschen locking. Das produziert manchmal die komischsten Fehler....

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo jaensen,

ja ich benutze einen Backgroundworker. Was meinst du mit "evtl. falschen locking"?

Gruß Dennis

2.760 Beiträge seit 2006
vor 15 Jahren

Wenn du aus mehreren Threads auf eine Resource zugreifst die nicht gelockt oder auf andere Art synchronisiert ist dann kann es passieren das der zugreifende Thread einen inkonsistenten Zustand vorfindet da der andere Thread seine Arbeit z.B. noch nicht vollständig abgeschlossen hat.

[Artikel] Multi-Threaded Programmierung ab Seite 8.

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo jaensen,

hmm das kann es eigentlich auch nicht sein. Es gibt nur einen Backgroundworker und dieser wird niemals gleichzeitig, immer nur hintereinander ausgeführt.

Gruß Dennis

2.760 Beiträge seit 2006
vor 15 Jahren

Das verringert nur die Wahrscheinlichkeit da die GUI auch in einem eigenen Thread läuft der natürlich auch noch dazwischenfunken kann. Bei Zugriffen auf Controls bekommst du eine CrossThreadViolation bei normalen Member-Variablen in den meisten Fällen nicht. Also schau mal ob irgendwo parallele Zugriffe vorkommen können bevor du das Thema ausschließt, wenn du nur einen BackgroundWorker verwendest sollte ja der evtl. betroffene Code gut einzuschränken sein.

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Es gibt eine DoWork-Klasse. In dieser Klasse wird der "ImageLoader" (siehe Methode im ersten Post) initialisiert, außerdem ist hier der Backgroundworker. Der Backgroundworker wird immer mal wieder gestartet und greift dann auf "ImageLoader" zu. Vermutlich stehen die Daten, sobald der Backgroundworker "neugestartet" wird, nicht mehr zur Verfügung. Wahrscheinlich ist das das Problem.

Habt ihr eine Idee, wie ich das ganze besser lösen kann?

Gruß Dennis

5.657 Beiträge seit 2006
vor 15 Jahren

Hi dennisspohr!

Das kann ich nicht nachvollziehen, aber das könntest du durch einfaches Debugging herausfinden. Die Frage ist ja nur, ob dein ImageLoader (bzw. die Bitmaps) einmalig neu erstellt werden, oder bei jedem Aufruf durch den Backgroundworker.
Du kannst ja auch (wenn es dein Klassenaufbau erlaubt) einfach den Backgroundworker deaktivieren, so daß das ganze synchron ausgeführt wird. Dadurch kannst du die Fehlerquelle besser eingrenzen.

Schöne Grüße,
Christian

Weeks of programming can save you hours of planning

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hi MrSparkle,

Die Frage ist ja nur, ob dein ImageLoader (bzw. die Bitmaps) einmalig neu erstellt werden, oder bei jedem Aufruf durch den Backgroundworker.

Der ImageLoader wird im gesamten Programmablauf nur einmal erstellt - genauso wie der Backgroundworker.

Du kannst ja auch (wenn es dein Klassenaufbau erlaubt) einfach den Backgroundworker deaktivieren, so daß das ganze synchron ausgeführt wird.

Das erfodert ein wenig Umstruktierung - aber ich werde es mal probieren.

Gruß Dennis

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo zusammen,

ich habe alles mal in einem einzigen Thread ausgeführt - immernoch der gleiche Fehler.

Gruß Dennis

5.657 Beiträge seit 2006
vor 15 Jahren

Hi dennisspohr,

dann poste doch mal die ImageLoader-Klasse, oder die (Bitmap-)relevanten Funktionen.
Du kannst übrigens beim Debuggen die Integrität der Bitmap-Objekte testen, indem du zu verschiedenen Zeitpunkten im Programm das Bitmap mit der Save-Methode in eine Datei speicherst.
Dann sollte der gleiche Fehler auftreten wie beim Zeichnen, und du kannst die Fehlerursache besser eingrenzen.

Schöne Grüße,
Christian

Weeks of programming can save you hours of planning

dennisspohr Themenstarter:in
420 Beiträge seit 2007
vor 15 Jahren

Hallo zusammen,

ich habe mein Projekt kopiert und alles irrelevante rausgenommen.
Was Witzige ist: Nun funktioniert es! Ich habe keinlei Ahnung warum.
Ich werde in den nächsten Tagen mal genau suchen / experimentieren.

Nochmal Danke für eure Hilfe!

Gruß Dennis