AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Threads (tpIdle) blokieren Anwendung
Thema durchsuchen
Ansicht
Themen-Optionen

Threads (tpIdle) blokieren Anwendung

Ein Thema von Manfred D2009 · begonnen am 14. Jun 2012 · letzter Beitrag vom 28. Jun 2012
Antwort Antwort
Seite 1 von 2  1 2      
Manfred D2009

Registriert seit: 2. Jun 2009
25 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

Threads (tpIdle) blokieren Anwendung

  Alt 14. Jun 2012, 14:50
Hi DP,

ich habe eine GUI-Anwendung mit mehreren Berechnungs-Threads. Die Threads haben für bestimmte Aufgaben synchronisierte Abschnitte. Diese Abschnitte sind notwendig und sehr kurz (wenige Millisekunden). Die Threads haben die Priorität tpIdle.

Wenn ich nun mehrere Threads starte, wird die Bedienung meiner Hauptanwendung sehr, sehr holprig, da die Threads durch das ständige Synchronisieren das Hauptprogramm blockieren (oft im Sekundenbereich).

Jetzt könnte ich weniger Threads starten oder in der Execute-Routine der Threads Sleep-Aufrufe platzieren, dann würde die Anwendung wieder rennen. Allerdings will ich, dass die Threads die größtmögliche Leistung haben, wenn in der Anwendung sonst nichts passiert.

Was kann ich machen, damit Idle-Prozesse auch wirklich "idle" sind?
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Threads (tpIdle) blokieren Anwendung

  Alt 14. Jun 2012, 15:29
Die Threads sind ja wirklich idle, nur Deine Synchronisation nicht. Synchronisation ist auch das, was bei Threads nahezu die größte Herausforderung ist.

Lösungsansätze hängen ab von der konkreten Problemstellung.

Ein Ansatz, den ich neulich verfolgt habe, ist, die Daten enifach in Blöcken zusammenzufassen. So hat mein Code etwa alle Dateien der Platte aufgelistet und jeweils nur Blöcke zu Hundert Dateinamen synchronisiert. Der verarbeitende Thread brauchte eh länger, so dass dies kein Problem darstellte.

Weiterhin ist die Frage, ob die Hauptanwendung tatsächlich synchronisieren muss. Wenn es um Weiterverarbeitung geht, wäre noch ein weiterer Thread doch auf gut genug. Oder ein threadsicheres Datenobjekt. Wenn es dann um Visualisierung geht, könnte das UI in einem angemessenen zeitlichen Abstand pollen statt für jedes neue Datum eine Synchronisierung reinzubekommen. Beispiel: wenn es darum geht, wieviele Dateien schon verarbeitet wurden, reicht es, etwa per TMultiReadExclusiveWriteSynchronizer (bzw. performanterer Varianten)-Objekt die Statistik zu befüllen und dort per Timer nur 10 mal die Sekunde abzufragen und auf die GUI zu klatschen.

Diese beiden sind aber auch nur zwei Ansätze von etlichen...
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Threads (tpIdle) blokieren Anwendung

  Alt 14. Jun 2012, 15:32
Da du deine Delphi Version nicht bekannt gibst schau doch mal, ob du Delphi-Referenz durchsuchenTThread.Queue schon hast. Das ist Synchronisieren ohne Blockieren
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Manfred D2009

Registriert seit: 2. Jun 2009
25 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Threads (tpIdle) blokieren Anwendung

  Alt 14. Jun 2012, 16:56
Danke für die schnellen Antworten!

@Sir Rufo:
Ich habe D2009
Das mit der Queue ist sicher ein interessanter Ansatz, geht aber leider bei mir nicht so einfach, da die Berechnungs-Threads, wenn sie erstmal dran sind, die Queue füllen und dann die GUI wieder nicht wie gewünscht zum Zug kommt. Außerdem wären die nötigen Umbaumaßnahmen sehr groß.

@CCRDude:
Zitat:
Die Threads sind ja wirklich idle, nur Deine Synchronisation nicht.
Mir ist klar, dass die Abarbeitung einer synchronisierten Methode im MainThread stattfindet. Aber müsste nicht eigentlich ein idle-Thread gar nicht erst zum Absetzen seiner Synchronize-Routine kommen, wenn das Hauptprogramm was tun will? Werden die idle-Threads vom Betriebssystem so "hochpriorisiert", dass diese ihre sync. Methoden absetzen können und so den MainThread ausbremsen?

Ich kann leider nicht so einfach auf die Synchronize-Geschichten verzichten, da ich Ausgaben machen muss und an manchen Stellen threadsichere Datenzugriffe brauche.

Gib es vielleicht eine Möglichkeit um festzustellen, ob vor/nach einer zu synchronisierende Routine der MainThread noch etwas Wichtiges zu tun hat. Wenn ja, könnte man die Threads ja kurz mal schlafen legen...
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#5

AW: Threads (tpIdle) blokieren Anwendung

  Alt 15. Jun 2012, 02:13
da die Berechnungs-Threads, wenn sie erstmal dran sind, die Queue füllen und dann die GUI wieder nicht wie gewünscht zum Zug kommt.
Mhm, dass klingt so, als ob die synchronisierten Stellen sehr oft aufgerufen werden.

In dem Zusammenhang:
und an manchen Stellen threadsichere Datenzugriffe brauche.
Vermutlich wärst du da mit CriticalSections oder anderen feingranularen Synchronisationsmitteln besser dran.


Aber müsste nicht eigentlich ein idle-Thread gar nicht erst zum Absetzen seiner Synchronize-Routine kommen, wenn das Hauptprogramm was tun will?
Ich denke eher, dass das das Hauptprogramm gerade den synchronisierten Teil ausführt, wenn der Nutzer eigentlich was interaktives Machen will. Außerdem könnte es sein, dass Synchronisierungs-Nachrichten von der Anwendung/Windows gegenüber UI-Nachrichten bevorzugt werden

Auf einem Multicore-System könnten theoretisch auch Hauptthread und Idle-Thread gleichzeitig ausgeführt werden.
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.

Geändert von BUG (15. Jun 2012 um 02:17 Uhr)
  Mit Zitat antworten Zitat
Manfred D2009

Registriert seit: 2. Jun 2009
25 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

AW: Threads (tpIdle) blokieren Anwendung

  Alt 15. Jun 2012, 08:15
@BUG:
Du hast recht, dass ich sehr häufig kleine synchronisierte Abschnitte lostrete. CriticalSections helfen zwar, die sync. Abschnitte zu verkleinern, aber auch in die threadsicheren Abschnitte darf trotzdem nur ein Prozess rein.

Und das Hauptproblem ist wohl, wie du sagst, dass auf einem Multicore-Rechner die Idle-Threads ja idle sind und deshalb weitermachen, ihre sync. Aufrufe loszuschicken.

Optimal für mich wäre eine Variante, bei der ich meine Threads bremse (evtl. mittels Sleep), wenn der Main-Prozess arbeitet und umgekehrt...
Gibt´s weitere Alternativen?
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#7

AW: Threads (tpIdle) blokieren Anwendung

  Alt 15. Jun 2012, 08:36
Hast du das EVA-Prinzip (Eingabe-Verarbeitung-Ausgabe) beachtet?
Ein Thread-Objekt bekommt alle seine Inputdaten als Kopie schon vor dem Start übergeben.
(z.B. über Properties der Threadklasse)
Soll ein Thread z.B. Daten per FTP herunterladen, dann bekommt er ein fertig initialisiertes IdFtpClient-Objekt übergeben.
Der Hauptthread gibt dem Thread von Aussen alles was er braucht; der Thread soll sich um nichts kümmern müssen.

Während der Thread läuft sollte die Synchronisierung mit dem Hauptthread auf ein Minimum beschränkt bleiben.
Nachdem der Thread fertig ist präsentiert er seine Ergebnisse über "Output"-Properties.
Der Hauptthread (benachrichtigt über das Event OnTerminate) holt sich die Daten ab und vereinigt sie ggf. mit den Daten der anderen Threads.

Natürlich kann diese Vorgehensweise nicht immer so eingehalten werden, weil die Aufgaben zu verschieden sind, aber es hat grosse Vorteile wenn man so vorgehen kann.

Geändert von sx2008 (15. Jun 2012 um 08:41 Uhr)
  Mit Zitat antworten Zitat
Manfred D2009

Registriert seit: 2. Jun 2009
25 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: Threads (tpIdle) blokieren Anwendung

  Alt 15. Jun 2012, 09:12
Zitat:
Hast du das EVA-Prinzip (Eingabe-Verarbeitung-Ausgabe) beachtet?...
...
Natürlich kann diese Vorgehensweise nicht immer so eingehalten werden, weil die Aufgaben zu verschieden sind, aber es hat grosse Vorteile wenn man so vorgehen kann.
Mir ist wie euch allen klar, das man auf diese sync. Abschnitte so gut es geht verzichten sollte und es wäre auch in meinem Sinn die Threads als BlackBox zu deklarieren und diese mit allem zu versorgen, was nötig ist (mache ich bereits zu einem größtmöglichen Teil). Allerdings muss Aufwand/Nutzen betrachtet werden und was bei der Threadentwicklung sehr schnell problematisch wird, wenn irgendwelche Bugs entstehen...

Das System läuft prinzipiell auch sehr gut. Nur, wie bereits erwähnt, gibt es Tuning-Probleme, wenn viele Threads laufen.
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#9

AW: Threads (tpIdle) blokieren Anwendung

  Alt 15. Jun 2012, 10:05
Das System läuft prinzipiell auch sehr gut.
Wenn es sekundenlang hängt, ist nicht sehr gut


Ich vermute mal, dass dein Hauptproblem ist, dass die Synchronisationsnachrichten gegenüber den "interaktiven" Nachrichten bevorzugt werden* und schlage folgendes vor:
  • Jeder Thread kann sich in eine eine threadsichere Queue eintragen, wenn der Thread etwas synchronisiertes machen möchte.
  • Der Thread schickt bei Wunsch, etwas synchronisiertes zu machen, eine niedrig-priore Nachricht an den Hauptthread.
  • Der Hauptthread kann, wenn er diese Nachricht erhält, die Queue abarbeiten und (mit CriticalSections gesicherte) Aktualisierungsprozeduren des Threads aufrufen.
Damit erreichst du, das du das Abarbeiten der "synchronisierten" Proceduren selbst kontrollierst und das nur passiert, wenn gerade Zeit ist.
Ob du das machen willst und dir damit das ganze Synchronisationszeug auf die Seele ziehst, ist natürliche deine Entscheidung

* Kann das jemand bestätigen oder verneinen? Man könnte das ja erstmal in einem Prototyp testen.
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.

Geändert von BUG (15. Jun 2012 um 10:21 Uhr)
  Mit Zitat antworten Zitat
Manfred D2009

Registriert seit: 2. Jun 2009
25 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#10

AW: Threads (tpIdle) blokieren Anwendung

  Alt 15. Jun 2012, 11:16
Zitat:
Wenn es sekundenlang hängt, ist nicht sehr gut
Wenn die Tuning-Probleme nicht wären, dann wär´s sehr, sehr gut!

Dein Ansatz mit einer threadsicheren Queue gefällt mir auf den ersten Blick richtig gut, das werde ich auf alle Fälle weiterverfolgen und ausprobieren!

Zitat:
•Jeder Thread kann sich in eine eine threadsichere Queue eintragen, wenn der Thread etwas synchronisiertes machen möchte.
•Der Thread schickt bei Wunsch, etwas synchronisiertes zu machen, eine niedrig-priore Nachricht an den Hauptthread.
•Der Hauptthread kann, wenn er diese Nachricht erhält, die Queue abarbeiten und (mit CriticalSections gesicherte) Aktualisierungsprozeduren des Threads aufrufen.
Was ich noch nicht ganz verstanden habe: Wie meinst du das mit "Thread soll niedrig priorisierten Message an den Hauptthread schicken"? Gibt es eine Möglichkeit die Messages zu priorisieren (hab ich noch nie gemacht)?
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 09:56 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