AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Bilder komprimieren und speichern mit Threads

Ein Thema von Schwedenbitter · begonnen am 28. Feb 2011 · letzter Beitrag vom 7. Mär 2011
Antwort Antwort
Medium
Online

Registriert seit: 23. Jan 2008
3.687 Beiträge
 
Delphi 2007 Enterprise
 
#1

AW: Bilder komprimieren und speichern mit Threads

  Alt 28. Feb 2011, 23:35
@Bummi: Wie sinnfrei ist das denn? Also, gut möglich, aber wenn die einzige Referenz im Thread liegt, warum sollte ich dann noch was locken müssen? Klingt für mich nach einer ziemlichen VCL-Nachlässigkeit bzw. Konzeptfehler. Ein Grund mehr, warum ich sowohl in Delphi als auch .NET praktisch grundsätzlich mit eignen Bitmapklassen arbeite, die ihre Daten in hübschen eindimensionalen, performaten Arrays halten. Der ganze Overhead in den diversen Grafikroutinen geht mir langsam auf die Nüsse... aber das nur so nebenbei, und ist ja nicht dein Verschulden =)

Was ich gern mache, ist einem Thread eine List<TAbzuarbeitendeObjektklasse> zu verpassen. Im Thread dann:
Delphi-Quellcode:
procedure Execute;
var
  ref: TAbgearbeiteteObjektklasse;
begin
  repeat
    if MyTaskList.Count>0 do
    begin
      ref := PerformTask(MyTaskList[0]);
      MyTaskList.Delete(0);
      SendMessage(hwndMyMainForm, WM_MYOBJECT_READY, Integer(ref), 0); // falls nötig, dass der MainThread die Fertigstellung mitbekommen muss
      // wobei ddas nicht ganz sauber ist, der MainThread muss dann gesichert "ref" verarbeitet oder kopiert haben, bevor das neue "ref" fertig ist.
      // Da ggf. eine weitere Queue nehmen, oder mit Flags arbeiten.
    end;
    Sleep(1);
  until Terminated;
end;
und im Hauptthread dann
Delphi-Quellcode:
procedure MyNewDataHandler(aObjectToHandle: TAbzuarbeitendeObjektKlasse);
begin
  MyThread.MyTaskList.Add(aObjectToHandle);
end;
Und wenn die zu verarbeitenden Objekte selbst aus einem Thread stammen, bekommt der einen Callback, der o.g. Prozedur auslöst, was wahlweise auch per Windows Message hübsch sein kann. Dadurch gibts dann einen Thread, der ständig auf neue Inputs wartet, und wenn etwas kommt es fix durchrattert, so schnell wie es eben geht, und dann einfach mal fertig damit ist. Die Ergebnisse aus dem Verarbeitungsthread könnten dann ggf. in gleicher Weise an einen Speicher- oder Netzwerk-Thread übergeben werden, der dann entsprechend weiter macht. Im Grunde einfaches Queuing nach FIFO Prinzip. Macht sich für so Arbeitsthreads ganz nett.

\\Edit: Hupps, Code war LIFO, sollte FIFO sein :>

\\Edit2: Natürlich kann man PerformTask() wieder einen neuen Thread auslösen lassen, wodurch man je nach Struktur noch mehr von Multicores profitieren würde, wenn die eigentliche Abarbeitung single-threaded ist. Seit Multicores so langsam Standard sind, nutz ich solche Modelle zumindest ausschweifend =). Dann ändert sich aber natürlich die Stelle fürs Benachrichtigen des Hauptthreads.

\\Edit3: Schleife geändert... zu viel C# in letzter Zeit, ich bring alles durcheinander =)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium ( 1. Mär 2011 um 00:29 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#2

AW: Bilder komprimieren und speichern mit Threads

  Alt 1. Mär 2011, 00:24
Zitat:
Wie sinnfrei ist das denn?
ich sprach lediglich über meine Erfahrungen, mehrere Threads die auf das Canvas der übergebenen Bitmaps zugegriffen haben, jeder sein eigenes Bitmap, keines der Bitmaps war irgendwo sichtbar, trotzdem gab es ohne Canvas.Lock ca. 50 % Artefakte.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Medium
Online

Registriert seit: 23. Jan 2008
3.687 Beiträge
 
Delphi 2007 Enterprise
 
#3

AW: Bilder komprimieren und speichern mit Threads

  Alt 1. Mär 2011, 00:33
Aha okay! Wenn mehrere Threads auf den Canvas zugreifen, dann ist's ja sonnenklar. Dann gehört das auch so
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#4

AW: Bilder komprimieren und speichern mit Threads

  Alt 1. Mär 2011, 11:49
Danke für Eure vielen Hinweise!

Ich habe mal angefangen und das Ergebnis sieht schon ganz gut aus. Auf mehrere Threads habe ich verzichtet, da wir hier in absehbarer Zeit sowieso vermutlich nie Rechner mit mehreren Kernen haben werden und es so einfacher zu strukturieren war. Ich habe meinen Code mal als Datei angehängt und würde mich freuen, wenn jemand noch gute Hinweise hat. Canvas muss erwartungsgemäß nicht gelocked werden.

Mir geht es insbesondere um das Aufräumen. Ich wollte mich nicht um den Thread kümmern müssen und habe daher FreeOnTerminate:=True; gesetzt. Aus diesem Grund muss ich TObjectList am Ende von TThread.Execute; freigeben, weil der Destructor so nicht aufgerufen wird, in dem ich das sonst getan hätte.
Ferner bin ich mir nicht sicher, ob ich innerhalb des Thread für das Hinzufügen bzw. Löschen von Bildern mit einer CriticalSection arbeiten muss/sollte. Es wäre ja sonst denkbar, dass in exakt demselben Moment mit nicht absehbaren Folgen ein Bild hinzugefügt und ein anderes gelöscht wird.

Den Code habe ich mit FastMM geprüft. Speicherlecks wurden keine angezeigt

Gruß, Alex
Angehängte Dateien
Dateityp: zip SaveThread_p.zip (3,0 KB, 10x aufgerufen)
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#5

AW: Bilder komprimieren und speichern mit Threads

  Alt 1. Mär 2011, 13:18
zumindest Append müsstest Du mit einer CS kapseln ...
ansonsten habe ich so ein komisches Bauchgefühl ...
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#6

AW: Bilder komprimieren und speichern mit Threads

  Alt 2. Mär 2011, 00:20
Zu früh gefreut:

Ich habe meinen Code jetzt mal unter realistischeren Bedingungen getestet. Dazu habe ich jeweils zwischen Append(); ein Sleep(); gepackt. Hintergrund ist der, dass der Scanner die Bilder auch nicht sofort auf einmal liefert.
Zudem habe ich den Thread zur besseren Lesbarkeit in eine eigene Unit gepackt.

Dabei ist mir ein weiterer Fehler aufgefallen.
Der Thread wird offenbar noch korrekt gestartet. Auch wenn das Ereignis an das MainForm erst später kommt, so sehe ich zeitnah nach dem Erstellen des Thread die 1. Datei auf dem Laufwerk erscheinen. Dann passiert aber lange nichts. Der Rest wird erst in die Dateien gespeichert, wenn alle Dateien geliefert wurden. Das ist aber leider nicht der Sinn vom Ganzen. Nach meinem Verständnis sollte der Thread, solange nicht Ende:=True; gesetzt ist, alles sofort wegspeichern, was in der Liste ist...

Ich habe die Änderungen vom Code wieder als zip-Datei angefügt und würde mich freuen, wenn mal jemand von den Profis drüber schauen und mir sagen könnte, wo mein Fehler liegt.

Gruß & Dank, Alex
Angehängte Dateien
Dateityp: zip SaveThread_2.zip (3,8 KB, 10x aufgerufen)
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#7

AW: Bilder komprimieren und speichern mit Threads

  Alt 2. Mär 2011, 07:48
Ich habe nicht alles nachvollzogen, aber ein paar Sachen sind mir aufgefallen:
1.) keine CS bei Append und Ende
2.) in diesem Block
Delphi-Quellcode:
FThread.Append(Bild);
Sleep(250);// -> 4 Bilder / 1 Sek.
läuft der Thread ja bereits.....
3.) wenn das:
Delphi-Quellcode:
Procedure TMainForm.RepeaterTimer(Sender: TObject);
Begin
   Repeater.Enabled:=False;
   ScannenClick(nil);
End;
ausgeführt wird, wird jedes mal eine neuer Thread losgetreten

Vielleicht schaut Sir Rufo mal drüber ....
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz