Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Thumbnails via Threads laden (https://www.delphipraxis.net/116956-thumbnails-via-threads-laden.html)

Nils_13 9. Jul 2008 10:05


Thumbnails via Threads laden
 
Hi,

ich möchte viele Thumbnail-Ladevorgänge in Threads auslagern. Wie könnte man das performant tun ? Ich dachte eine Zeit lang an eine Rekursion. Ein Thread arbeitet, wenn fertig wird der nächste erstellt, welcher wieder arbeitet. Dies würde so lange ablaufen, bis nichts mehr übrig ist. Es zu programmieren erschien mir allerdings unmöglich. Daher dachte ich an mehrere Threads welche mit Critical Sections gesichert sind. So wie ich das sehe bräuchte ich dann ein Array of TThumbnailThread (TThumbnailThread ist eine Ableitung von TThread). Brauche ich das wirklich ? Denn ich denke das wäre ab einer gewissen Anzahl von zu ladenden Thumbnails sehr belastend. Gibt es noch andere Lösungsmöglichkeiten ?

Apollonius 9. Jul 2008 10:53

Re: Thumbnails via Threads laden
 
Du solltest nicht viel mehr Threads erstellen als CPU-Kerne vorhanden sind (wobei Hyperthreading-Kerne mehrfach gezählt werden sollten, aber das ist nicht so wichtig). Sonst gibt es nämlich nur mehr Overhead.
Du könntest das Ganze gut mit einer Auftragsliste implementieren: Jedes zu bearbeitende Bild ist ein Auftrag. Wenn du die noch ausstehenden und beendeten Aufträge in einer Linked List speicherst, kommst du sogar ohne Critical Sections aus.

Nils_13 9. Jul 2008 11:11

Re: Thumbnails via Threads laden
 
Wäre es dann nicht schwierig die geladenen Bilder zurückzugeben ? Es soll nämlich nach jedem geladenen Bild dieses auch in der ListView erscheinen.

Apollonius 9. Jul 2008 11:28

Re: Thumbnails via Threads laden
 
Das sollte kein riesiges Problem darstellen. TThread bietet die Möglichkeit, dem Hauptthread Arbeiten zuzuteilen, und zwar nicht blockierend wie bei Synchronize (Klassenmethode Queue). Da könntest du dann einfach immer ein Aktualisierungsroutine angeben. Am besten führst du einfach eine globale boolsche Variable ein: Sie hat den Status False, wenn die Routine gerade nicht in der Warteschlange steckt, ansonsten True. Am Anfang der Aktualisierungsmethode setzt du sie auf false und holst so viele Thumbnails wie möglich aus deiner Liste der fertigen Aufträge. Wenn ein Thread einen Auftrag bearbeitet hat, setzt er den Status der globalen Variable mit InterlockedExchange auf True und fügt, falls die Variable vorher den Wert False hatte, die Aktualisierungsroutine der Warteschlange hinzu.

Um das deutlich zu machen:
Delphi-Quellcode:
var GlobalFlag: Boolean;

procedure ThreadRoutine;
var Job: TThumbnailJob;
begin
  while DequeueJob(JobsToDo, Job) do
  begin
    Job.Execute;
    QueueJob(ExecutedJobs, Job);
    if InterlockedExchange(Integer(GlobalFlag), Integer(True)) = Integer(False) then
      TThread.Queue(nil, MyForm.UpdateListView);
  end;
end;

procedure TMyForm.UpdateListView;
var Job: TThumbnailJob;
begin
  GlobalFlag := false;
  while DequeueJob(ExecutedJobs, Job) do
  begin
    AddThumbnailToListView(Job);
    Job.Free;
  end;
end;

Nils_13 9. Jul 2008 11:59

Re: Thumbnails via Threads laden
 
Wäre dann JobsToDo eine LinkedList ?

Apollonius 9. Jul 2008 12:02

Re: Thumbnails via Threads laden
 
Das wäre das Effektivste. Du kannst natürlich auch eine TObjectQueue mit einer Critical Section oder was auch immer verwenden, aber der große Vorteil von verketteten Listen ist, dass du kein Synchronisations-Objekt benötigst. Allerdings ist die Implementierung nicht ganz trivial, du brauchst die Interlocked-Funktionen. Windows bietet aber entsprechende Funktionen an; es handelt sich zwar um einen Stack und nicht um eine Queue, aber das sollte eigentlich egal sein.

Nils_13 9. Jul 2008 12:13

Re: Thumbnails via Threads laden
 
Ich frage mich gerade ganz ehrlich, was überhaupt wirklich eine LinkedList ist. Stehen nicht in der Liste dann die ganzen Thumbnails drinnen ? Damit es funktioniert muss ich allerdings einen eigenen Datentyp übergeben, weil sonst der Thread zu wenig Informationen besitzt um zu arbeiten. Dafür kann ich eigentlich nur ein Array of TDatentyp nehmen. Abgesehen davon gilt noch zu beachten, dass es nicht zu sehr auf der API basieren sollte. Daher habe ich extra TThread und nicht BeginThread genommen.

Apollonius 9. Jul 2008 12:14

Re: Thumbnails via Threads laden
 
TThumbnailJob ist eine Klasse mit allen benötigten Informationen. Wenn du die API nicht verwenden willst und du nichts gegen ein kleines bisschen Overhead hast, kannst du auch einfach eine TThreadList nehmen.

Nils_13 9. Jul 2008 12:54

Re: Thumbnails via Threads laden
 
Und in diese Liste kommen alle noch abzuarbeitenden Bilder rein ?

Apollonius 9. Jul 2008 16:24

Re: Thumbnails via Threads laden
 
Ja. Du hast zwei Listen, eine für die fertigen Aufträge und eine für die noch ausstehenden. Jeder Auftrag wird durch eine Objektinstanz repräsentiert, die die Bilder, eventuell andere Einstellungen und das fertige Thumbnail (das ist natürlich nur in der Liste der fertigen Aufträge zugewiesen) enthält.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:38 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz