AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Threads mit Oberfläche synchronisieren (VCL)

Threads mit Oberfläche synchronisieren (VCL)

Ein Tutorial von sakura · begonnen am 25. Jan 2017 · letzter Beitrag vom 26. Jan 2017
Antwort Antwort
Benutzerbild von sakura
sakura
Registriert seit: 10. Jun 2002
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 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.

......

Keine Ahnung, wie ich Anhänge updaten kann, korrigierte Version weiter unten: http://www.delphipraxis.net/191536-t...ml#post1360002
Angehängte Dateien
Dateityp: zip Threading.zip (8,2 KB, 43x aufgerufen)
Ich bin nicht zurück, ich tue nur so

Geändert von sakura (26. Jan 2017 um 09:48 Uhr) Grund: Update des Anhangs.
 
a.def
 
#2
  Alt 25. Jan 2017, 16:23
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?
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

 
Delphi 7 Personal
 
#3
  Alt 25. Jan 2017, 16:26
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
  Mit Zitat antworten Zitat
a.def
 
#4
  Alt 25. Jan 2017, 16:30
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
  Mit Zitat antworten Zitat
norwegen60

 
Delphi 10.2 Tokyo Professional
 
#5
  Alt 25. Jan 2017, 16:32
Zitat:
anbei habe ich ein kleines Beispiel für die Synchronisierung von Threads mit der Anzeige erstellt.
Danke
  Mit Zitat antworten Zitat
a.def
 
#6
  Alt 25. Jan 2017, 16:35
So wie ich das jetzt verstanden habe sendet man eine Message und die wertet der Thread dann mit Peek aus.
So wie if myMessage.message = vclDoUpdatem then dann darf man updaten?
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

 
Delphi 10.2 Tokyo Professional
 
#7
  Alt 25. Jan 2017, 16:39
So wie ich das jetzt verstanden habe sendet man eine Message und die wertet der Thread dann mit Peek aus.
So wie if myMessage.message = vclDoUpdatem then dann darf man updaten?
Stopp, dazu bitte eine eigene Diskussion starten, da es hier ausschließlich um das Tutorial geht, sonst geht die Übersicht verloren.

Danke
......
Daniel W.
  Mit Zitat antworten Zitat
norwegen60

 
Delphi 10.2 Tokyo Professional
 
#8
  Alt 25. Jan 2017, 17:28
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

Geändert von norwegen60 (25. Jan 2017 um 17:31 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

 
Delphi 10.2 Tokyo Professional
 
#9
  Alt 26. Jan 2017, 09:48
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

Korrigierte Version im Anhang.
Angehängte Dateien
Dateityp: zip Threading.zip (8,2 KB, 35x aufgerufen)
Daniel W.
  Mit Zitat antworten Zitat
Themen-Optionen Tutorial durchsuchen
Tutorial durchsuchen:

Erweiterte Suche
Ansicht

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 14:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf