Delphi-PRAXiS
Seite 5 von 5   « Erste     345   

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 Kann ich meine ListView beschleunigen (Icon laden dauert ewig) (https://www.delphipraxis.net/198553-kann-ich-meine-listview-beschleunigen-icon-laden-dauert-ewig.html)

Schokohase 13. Nov 2018 18:48

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1418007)
Delphi-Quellcode:
TThread.Destroy
ruft
Delphi-Quellcode:
TThread.RemoveQueuedEvents
auf

jetzt wo du es sagst ... stimmt, da war noch was

KodeZwerg 13. Nov 2018 22:29

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
Das mit dem TParallel.For() bekomme ich auch nicht wirklich in Gange.
Zum verzweifeln wenn man nicht weiß wie.
Delphi-Quellcode:
procedure TfrmMain.StartIcons3( AListView: TListView; AImageList: TImageList );
var
  LIcon: TIcon;
  dummy: Word;
begin
  dummy := 0;
  LIcon := TIcon.Create;
  LIcon.Transparent := True;
  TParallel.For(0, AListView.Items.Count - 1,
    procedure(Index: Integer; State: TParallel.TLoopState)
    var
      Filename : string;
    begin
      try
        if State.ShouldExit then Exit;
        TThread.Synchronize(nil,
          procedure
          begin
            Filename := AListView.Items.Item[ Index ].Caption;
            LIcon.Handle := ExtractAssociatedIcon( hInstance, PWideChar( Filename ), dummy );
            LIcon.Transparent := True;
            AListView.Items.Item[Index].ImageIndex := AImageList.AddIcon( LIcon );
            DestroyIcon( LIcon.Handle );
          end);
      finally
      end;
    end);
  LIcon.Free;
end;

EWeiss 13. Nov 2018 22:51

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
Zitat:

Übergibt man beim Queue ein nil, kommen die Events auch noch an wenn der auslösende Thread schon weg ist.
Ok hilft dir jetzt nicht weiter möchte aber doch noch darauf antworten.

@Uwe Raabe
Du bist Profi ohne frage;)
Aber das Phänomen konnte ich bisher in realer Anwendungsumgebung bisher so nicht ausmachen.
Wenn der Thread bei mir geschlossen wird dann ist da nix mehr mit Events auch bei Queue nicht.

Wie bei meinem Mixer.. also wie soll dann der System Mixer Events an meinen Thread schicken können wenn er weg ist.
Nun er kann es versuchen, hat aber keine Auswirkung da sie nicht verarbeitet werden können bzw. kommen nicht mehr an.

gruss

Uwe Raabe 13. Nov 2018 23:32

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von EWeiss (Beitrag 1418016)
Aber das Phänomen konnte ich bisher in realer Anwendungsumgebung bisher so nicht ausmachen.
Wenn der Thread bei mir geschlossen wird dann ist da nix mehr mit Events auch bei Queue nicht.

Wie bei meinem Mixer.. also wie soll dann der System Mixer Events an meinen Thread schicken können wenn er weg ist.
Nun er kann es versuchen, hat aber keine Auswirkung da sie nicht verarbeitet werden können bzw. kommen nicht mehr an.

Der Begriff "Event" ist hier nicht im Sinne der Windows-API oder eines Delphi-Methodenzeigers zu verstehen, sondern im wörtlichen Sinne als Ereignis, das von einem Queue-Aufruf im Thread ausgelöst und im Hauptthread abgearbeitet wird.

Wenn du innerhalb eines Threads einen Queue-Aufruf machst, dann wird der erstmal in die Warteschlange gelegt, bis der Hauptthread ihn abarbeitet. Im Gegensatz zu Synchronize arbeitet der Thread aber sofort weiter und kann sich natürlich auch beenden. Sollte das passieren bevor die Warteschlange vollständig abgearbeitet wurde, dann entfernt das TThread.Destroy noch eben schnell alle Queue-Calls aus der Warteschlange, die noch einen Verweis auf den besagten Thread haben.

Es handelt sich natürlich um eine Race Condition, was ein konkretes Beispiel schwer macht. Das Phänomen kann man aber häufig mit dem anhängenden (sinnfreien) Beispiel provozieren. Je nachdem welchen der beiden Queue-Aufrufe man verwendet kommt entweder nur ein Teil oder alle Zahlen im Memo an.

EWeiss 13. Nov 2018 23:39

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
Zitat:

sondern im wörtlichen Sinne als Ereignis
Ja nun es sind diese die mir vom System Mixer geschickt werden.
Diese Events nehme ich an und schicke sie zum Mainthread mehr ist da nicht.

Vielleicht verstehe ich dich auch nicht so recht was genau gemeint ist.
Es geht nicht um Threads von meiner Anwendung zu meiner DLL und umgekehrt sondern um Threads vom System zur Anwendung.

Und da kann ich solche Probleme nicht feststellen.

Zitat:

dann wird der erstmal in die Warteschlange gelegt, bis der Hauptthread ihn abarbeitet
Jo nichts anderes als PostMessage im weitläufigen sinne.
Na ja auf jeden fall.. Danke für die Infos.

gruss

Uwe Raabe 13. Nov 2018 23:49

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
Zitat:

Zitat von EWeiss (Beitrag 1418019)
Jo nichts anderes als PostMessage im weitläufigen sinne.

Nur das Queue eben nicht mit PostMessage arbeitet (muss ja auch für die anderen Plattformen gehen). Wenn man das Szenario mal theoretisch mit der Windows Message Queue umsetzen wollte, dann würde der Thread beim Beenden noch schnell alle PostMessage Calls, die er gemacht hat und die noch in der Message Queue drin stecken einfach da rauslöschen.

@Alle: Es würde mich prinzipiell mal interessieren, ob mein Beispiel auch auf anderen Systemen das Problem verlässlich nachbildet.

KodeZwerg 14. Nov 2018 03:07

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
So macht es mehr oder weniger was ich wollte, nun werden nach und nach die icons geladen und dargestellt unabhängig vom mainthread.

Delphi-Quellcode:
procedure TfrmMain.StartIcons3();
begin
  TThread.CreateAnonymousThread(procedure ()
    var
      LIcon: TIcon;
      dummy: Word;
      I: Integer;
    begin
      FileIcons.BeginUpdate;
      LIcon := TIcon.Create;
      LIcon.Transparent := True;
      lvFiles.Column[0].MinWidth := 37;
      lvFiles.Column[0].MaxWidth := 37;
      lvFiles.Column[0].Width := 37;
      lvFiles.SmallImages := FileIcons;
      try
        for i := 0 to lvFiles.Items.Count -1 do
          begin
            dummy := 0;
            TThread.Synchronize (TThread.CurrentThread,
              procedure ()
                begin
                  LIcon.Handle := ExtractAssociatedIcon( hInstance, PWideChar( lvFiles.Items.Item[ i ].Caption ), dummy );
                end);
            LIcon.Transparent := True;
            dummy := FileIcons.AddIcon( LIcon );
            DestroyIcon( LIcon.Handle );
            TThread.Synchronize (TThread.CurrentThread,
              procedure ()
                begin
                  lvFiles.Items.Item[ i ].ImageIndex := dummy;
                end);
          end;
      finally
        TThread.Synchronize (TThread.CurrentThread,
          procedure ()
            begin
              FileIcons.EndUpdate;
            end);
        LIcon.Free;
      end;
    end).Start;
end;

TiGü 14. Nov 2018 07:58

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1418020)
@Alle: Es würde mich prinzipiell mal interessieren, ob mein Beispiel auch auf anderen Systemen das Problem verlässlich nachbildet.

Ja, es zeigt es ganz gut (Win 10, 10.2.3).
Mit der Verwendung von procedure
Delphi-Quellcode:
TThread.Queue(AThreadProc: TThreadProcedure);
wird beim Zerstören des Threads alle Warteschlangen-Ereignisse entfernt - da dann hier Self verwendet wird - und man kommt nie bis zur Zahl 100 im Memo.
Oft kommt auch gar nichts an (das hat mich dann doch überrascht).

Wenn man es umschreibt und
Delphi-Quellcode:
class procedure TThread.Queue(const AThread: TThread; AMethod: TThreadMethod);
mit nil als ersten Parameter verwendet, dann arbeitet der Hauptthread noch alles ab.
Hier geht das natürlich und ist unkritisch, aber wehe, man hat richtigen Code und greift auf Ressourcen des Threads zu.
Vielen Dank, wieder was gelernt. :thumb:

CCRDude 14. Nov 2018 08:30

AW: Kann ich meine ListView beschleunigen (Icon laden dauert ewig)
 
Ich finde es gerade nirgendwo dokumentiert, aber so wie die VCL nicht thread-safe ist, würde ich nie Windows-Handles zwischen Threads austauschen. Das knallt im Zweifel irgendwann irgendwo ohne dass man den Kontext erkennt.
Den Icon-Stream zwischen den Threads auszutauschen hat zudem den Vorteil, dass Duplikate einfach vermieden werden können. Und ein Icon-Cache macht gerade bei Netzwerklaufwerken enorm sein.
Spätestens dann machen anonyme Methoden/Threads immer weniger Sinn und schaden massiv der Übersichtlichkeit.

Ich würde das so umsetzen (da fehlt noch ein wenig Fehlerbehandlung, und verbessern kann man natürlich immer):
https://github.com/CCRDude/tlistview-icon-cache-demo
Ist LCL, aber VCL dürfte identisch sein, lediglich die Generics müssten angepasst werden, da nutze ich FreePascal sonst immer im objpas-Modus und bin mir nicht sicher, wie die entsprechenden Delphi-Klassen heißen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:38 Uhr.
Seite 5 von 5   « Erste     345   

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