Delphi-PRAXiS
Seite 2 von 2     12   

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)

alzaimar 9. Jul 2008 16:53

Re: Thumbnails via Threads laden
 
Ich habe hier irgendwo eine 'WorkerThreadPool' Klasse geschrieben, die Dir eigentlich die Arbeit abnimmt. Du musst nur noch den Job definieren und dann gehts los. Such mal danach, ich glaube, sie funktioniert. :zwinker:
Zitat:

Zitat von Apollonius
Du solltest nicht viel mehr Threads erstellen als CPU-Kerne vorhanden sind

Das würde ich nicht so pauschal aussagen. Nehmen wir an, Dein Thread soll Daten laden, wobei die Gegenseite der Bottleneck ist, also ziemlich langsam. Jeder Thread verbindet sich mit einer anderen (lahmen) Gegenstelle. Wenn Du nun 10 Threads am Laufen hast, warten die alle und die CPU langweilt sich immer noch; Du könntest also sehr viele Threads erzeugen, die dann gleichzeitig (ziemlich langsam) Daten einlesen, ohne die CPU überhaupt großartig zu belasten.

Ein konkretes Beispiel ist ein Portscanner: Ich erstelle sehr viele Threads, die parallel jeweils einen Port an der Gegenstelle abfragen, dabei müssen sie Timeout-Intervalle beachten. Jeder Thread wartet also z.B. 10 Sekunden auf einen Timeout. Damit ich nun nicht 65.000 * 10 Sekunden Warten muss, was doch eine ganze Weile ist, kann ich einfach jeweils 100 Threads parallel laufen lassen und warten dann nur knapp ein 1/100 der Zeit (erschlag mich nicht, wenn die 10 Sekunden Timeout zu kurz sind).

Ein weiteres Beispiel ist ein TCP-Server, der für jede einkommende Verbindung einen eigenen Thread aufmacht. Wieso sollte das auf 1-8 Threads beschränkt sein? Viel zu tun hat so ein TCP-Thread i.a. ja nicht.

Bei Dir wäre der Bottleneck vermutlich die Festplatte. So ein Thread wartet eine kurze Zeit, bis das Bild geladen ist. In der Zeit kann ein anderer Thread bereits mit der Berechnung des Thumbnails anfangen usw. Bevor Du jedoch Threads basteltst, würde ich vielleicht die Thumbnailerstellung optimieren (wenn da was zu holen ist).

Apollonius 9. Jul 2008 16:58

Re: Thumbnails via Threads laden
 
Ja, wenn die Threads warten, ist das klar. Ich ging allerdings davon aus, dass die Bilder bereits im Speicher vorliegen und nur noch ein Verkleinerungsalgorithmus durchgeführt werden muss. Andernfalls hast du natürlich recht, Alzaimar.

Nils_13 9. Jul 2008 17:04

Re: Thumbnails via Threads laden
 
Ich finde zu WorkerThreadPool nichts. Ich habe die Bilder nicht im Speicher liegen. Denn das kostet schließlich am meisten Zeit. Beim Laden und Generieren lässt sich nichts mehr verbessern denke ich. Was wäre also am sinnvollsten ? Ich habe außerdem folgenden leicht fehlerhaften Code geschrieben, welcher wenigstens mal etwas funktioniert. Scheinen aber wirklich Fehler drinnen zu sein, die ich gerade nicht finde - gewisse Bilder sind einfach schwarz, wechselt man das Verzeichnis (ist ein Dateiverwaltungsprogramm) werden die Bilder nicht neu geladen usw. Scheint aber am ThumbnailDone zu liegen. Ich habe das Gefühl, es sei allgemein aber noch etwas instabil.
Delphi-Quellcode:
type
  TDone = procedure (Items : TDynItemArray) of object;
  TThumbnailThread = class(TThread)
  private
    fDone : TDone;
    procedure SyncDone;
  protected
    procedure Execute; override;
  public
    Items : TDynItemArray;
    Img  : TImageList;
    property Done : TDone read fDone write fDone;
  end;

procedure TThumbnailThread.Execute;
var i      : Integer;
    Picture : TPicture;
    Bmp    : TBitmap;
begin
  try
    for i := 0 to High(Items) do
    begin
      try
        Picture := TPicture.Create;
        Picture.LoadFromFile(Items[i].Pfad+Items[i].Name);
        Bmp := TBitmap.Create;
        with Bmp do
        begin
          ...
          Img.Add(Bmp, nil);
          Items[i].ImageIndex := Pred(Img.Count);
          Free;
        end;
      except

      end;
      SyncDone;
    end;
  except
    on e: exception do
    begin

    end;
  end;
end;

procedure TThumbnailThread.SyncDone;
begin
  if Assigned(fDone) then
    fDone(Items);
end;

procedure TRazFileManager.LoadThumbnails;
var Thread : TThumbnailThread;
begin
  Thread := TThumbnailThread.Create(True);
  with Thread do
  begin
    Items := Thumbnails;
    Img  := Img32;
    Done := ThumbnailDone;

    Resume;
  end;
end;

procedure TRazFileManager.ThumbnailDone(Items : TDynItemArray);
var i : Integer;
begin
  for i := 0 to High(Items) do
    DirsFiles[DirCount+Items[i].Index].ImageIndex := Items[i].ImageIndex;          
end;
Edit: habe einen wichtigen Fehler gefunden und beseitigt. Nun scheint es ganz gut zu laufen.

Die Muhkuh 9. Jul 2008 17:35

Re: Thumbnails via Threads laden
 
Zitat:

Zitat von Nils_13
Ich finde zu WorkerThreadPool nichts.

:arrow: http://www.delphipraxis.net/internal...t.php?t=111982

alzaimar 10. Jul 2008 09:05

Re: Thumbnails via Threads laden
 
Deine Imageliste ist nicht thread-safe. Wenn zwei threads gleichzeitig darauf zugreifen, gibts Probleme. Du musst den Zugriff mit TCriticalSections synchronisieren. Weiterhin ist die TImageList eine VCL-Komponente und diese Komponenten dürfen nur im Hauptthread verwendet werden (z.B. mit Synchronize).

Ich würde an Deiner Stelle erst die Thumbnailerstellung 100% richtig hinbekommen und erst dann mal mit Threads rumexperimentieren. Zu viel auf einmal macht einen nur konfus, und man weiss gar nicht, wo man einen Fehler suchen soll.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:48 Uhr.
Seite 2 von 2     12   

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