Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Tutorials und Kurse (https://www.delphipraxis.net/36-tutorials-und-kurse/)
-   -   Threads mit Oberfläche synchronisieren (VCL) (https://www.delphipraxis.net/191536-threads-mit-oberflaeche-synchronisieren-vcl.html)

sakura 25. Jan 2017 15:08

Threads mit Oberfläche synchronisieren (VCL)
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,

anbei habe ich ein kleines Beispiel für die Synchronisierung von Threads mit der Anzeige erstellt.

Was wird demonstriert

In der Demo-Anwendung werden vier Szenarien demonstriert. Einmal Threads mit wenig Arbeit bis zur Darstellung von Informationen, und einmal Threads, welche mehr erledigen müssen, bevor Daten dargestellt werden. Beide Varianten stellen die Daten einmal direkt in der Anwendung dar (mittels Synchronize) und einmal mittels einem Zwischenspeicher. (2 x 2 Varianten = 4 verschiedene Szenarien).

Wie wird demonstriert

Die Demo besteht aus zwei Units
  1. MainForm: Anzeige der Werte und Steuerung der Threads

    Über die RadioGroup kann der Demo-Modus ausgewählt werden.
    Beim Klick auf den RUN-Button werden 5 Threads mit verschiedenen Startwerten erstellt.
    Im Label (ganz unten) wird dargestellt, wieviele Threads laufen, bzw. wie lange die Verarbeitung gedauert hat.
    Der Timer lädt generierte Daten in das Memo (wenn, welche vorhanden sind)
  2. Threads: Stellt die Thread-Klasse zur Verfügung

    Ein Klasse für alle Szenarien. Berechnet wird die Summe aller Zahlen von 1 bis zum übergebenen Startwert.
    Wenn ein hoher Aufwand simuliert wird, wird nach jeder Addition eine kleine Pause eingelegt (Sleep).
    Anschließend wird der aktuelle Zwischenstand verkündet. Entweder über eine direkte Darstellung in der Oberfläche, ober die Daten werden in eine threadsichere Liste gespeichert.

Was wird NICHT demonstriert

Der gemeinsam genutzte Speicher
Delphi-Quellcode:
TMyData = TThreadList<string>;
ist nicht die performanteste Variante, aber sie ist leicht zu verstehen. Je nach Datentypen, welche synchronisiert werden, muss man sich Gedanken machen, wie diese hinterlegt werden. Das kann eine Datenbank sein, eine einfache Variable, eine Klasse, oder wie hier gezeigt eine threadsichere Liste, oder, oder, oder...

Sleep() ist nicht die beste Methode, einen hohen Workload zu simulieren, da der Thread nichts zu tun hat, für die Demo ist es aber ausreichend.

Werte der Szenarien

Wenig Arbeit
  • Direkt synchronisieren
    875 ms
    als Basiswert: 100%
  • mittels Zwischenspeicher synchronisieren
    16 ms
    relativ: 1,8%

Viel Arbeit
  • Direkt synchronisieren
    7000 ms
    als Basiswert: 100%
  • mittels Zwischenspeicher synchronisieren
    5718 ms
    relativ: 81,7%

Man erkennt also, dass, je mehr der Thread wirklich arbeitet, der Vorteil des Zwischenspeichers abnimmt. Aber, es ist immer noch eine signifikante Verbesserung (20%), welche gerade bei langwierigen Aufgaben bemerkbar wird.

Erkenntnisse: Threads manchmal eventuell useless

Gerade wenn Threads viele Informationen an die UI senden, und diese mittels Synchronize durchgeführt werden, fällt auf, dass es schnell dazu kommt, dass die UI nicht mehr auf User-Aktivitäten reagiert, da die Synchronisierung zu viel Zeit in Anspruch nimmt.

Abschließende Worte

Bei diesem Tutorial geht es nicht so sehr um die Verwendung von Threads, und wie man diese nutzt, sondern um ein einfaches Beispiel, wie ihr die generierten Daten zur Laufzeit in die Oberfläche bekommt. Dabei ist es sicherlich nicht sinnvoll, so wie hier gezeigt, jeden einzelnen Schritt darzustellen.

...:cat:...

Keine Ahnung, wie ich Anhänge updaten kann, korrigierte Version weiter unten: http://www.delphipraxis.net/191536-t...ml#post1360002

a.def 25. Jan 2017 15:23

AW: Threads mit Oberfläche synchronisieren (VCL)
 
Nettes Tutorial! Dazu habe ich gleich eine Frage.

Ich nutze seit langer Zeit einen etwas anderen Ansatz. Ich habe einen Thread der länger arbeiten muss. In diesem Thread weise ich einer gewissen Variablen (es ist ein Record, ich setze einen String im Rekord) einen Wert zu.
Dieser Wert wird von einem anderen Thread überprüft und sobald eine Änderung + zeitliche Verzögerung von mindestens Zeit-X vorhanden ist wird synchronisiert. Mein Arbeiter-Thread synchronisiert nicht.

Was ist davon zu halten?

p80286 25. Jan 2017 15:26

AW: Threads mit Oberfläche synchronisieren (VCL)
 
Zitat:

Zitat von a.def (Beitrag 1359944)
Nettes Tutorial! Dazu habe ich gleich eine Frage.

Ich nutze seit langer Zeit einen etwas anderen Ansatz. Ich habe einen Thread der länger arbeiten muss. In diesem Thread weise ich einer gewissen Variablen (es ist ein Record, ich setze einen String im Rekord) einen Wert zu.
Dieser Wert wird von einem anderen Thread überprüft und sobald eine Änderung + zeitliche Verzögerung von mindestens Zeit-X vorhanden ist wird synchronisiert. Mein Arbeiter-Thread synchronisiert nicht.

Was ist davon zu halten?

Pollen ist immer unoptimal. Eine Alternative sind Messages.
Gruß
K-H

a.def 25. Jan 2017 15:30

AW: Threads mit Oberfläche synchronisieren (VCL)
 
Wie sähe das Gegenteil von Pollen denn mit einem Thread und Messages aus? (der Arbeiter-Thread pusht ja [setzt Variablen] und der andere ließt sie aus [pull])
Und kann ich dann trotzdem noch meine Variablen setzen wie aktuell auch

norwegen60 25. Jan 2017 15:32

AW: Threads mit Oberfläche synchronisieren (VCL)
 
Zitat:

anbei habe ich ein kleines Beispiel für die Synchronisierung von Threads mit der Anzeige erstellt.
Danke:thumb:

a.def 25. Jan 2017 15:35

AW: Threads mit Oberfläche synchronisieren (VCL)
 
So wie ich das jetzt verstanden habe sendet man eine Message und die wertet der Thread dann mit Peek aus.
So wie
Delphi-Quellcode:
if myMessage.message = vclDoUpdatem then
dann darf man updaten?

sakura 25. Jan 2017 15:39

AW: Threads mit Oberfläche synchronisieren (VCL)
 
Zitat:

Zitat von a.def (Beitrag 1359949)
So wie ich das jetzt verstanden habe sendet man eine Message und die wertet der Thread dann mit Peek aus.
So wie
Delphi-Quellcode:
if myMessage.message = vclDoUpdatem then
dann darf man updaten?

:warn: Stopp, dazu bitte eine eigene Diskussion starten, da es hier ausschließlich um das Tutorial geht, sonst geht die Übersicht verloren.

Danke
...:cat:...

norwegen60 25. Jan 2017 16:28

AW: Threads mit Oberfläche synchronisieren (VCL)
 
Habe das Tutorial angeschaut und folgende festgestellt:
  1. Bei "Wenig Arbeit, nicht synchronisieren" erscheinen bei mir keine Werte im Memo-Fenster
  2. Ich denke, dass der Thread die Liste dauergeblockt hat und dadurch der Timer keine Möglichkeit hatte sie zu kopieren. Und dann wird er beendet bevor er noch mal die Möglichkeit hat. Sobald ich in OnThreadDone den tmrSyncTimer noch manuell aufrufe geht es
    Delphi-Quellcode:
      tmrSync.Enabled := False;
      tmrSyncTimer(nil);          // Am Schluss noch mal manuell Sync aufrufen

sakura 26. Jan 2017 08:48

AW: Threads mit Oberfläche synchronisieren (VCL)
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von norwegen60 (Beitrag 1359961)
Bei "Wenig Arbeit, nicht synchronisieren" erscheinen bei mir keine Werte im Memo-Fenster

Es war nicht die Blockade, sondern lediglich der Fall, dass der Timer nicht ausgelöst hat, bevor dieser wieder beendet wurde, ging einfach alles zuuuu schnell :D

Korrigierte Version im Anhang.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:18 Uhr.

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