![]() |
Threads (tpIdle) blokieren Anwendung
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? |
AW: Threads (tpIdle) blokieren Anwendung
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... |
AW: Threads (tpIdle) blokieren Anwendung
Da du deine Delphi Version nicht bekannt gibst ;) schau doch mal, ob du
![]() |
AW: Threads (tpIdle) blokieren Anwendung
Danke für die schnellen Antworten!
@Sir Rufo: Ich habe D2009 :wink: 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:
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... |
AW: Threads (tpIdle) blokieren Anwendung
Zitat:
In dem Zusammenhang: Zitat:
Zitat:
![]() Auf einem Multicore-System könnten theoretisch auch Hauptthread und Idle-Thread gleichzeitig ausgeführt werden. |
AW: Threads (tpIdle) blokieren Anwendung
@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? |
AW: Threads (tpIdle) blokieren Anwendung
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. |
AW: Threads (tpIdle) blokieren Anwendung
Zitat:
Das System läuft prinzipiell auch sehr gut. Nur, wie bereits erwähnt, gibt es Tuning-Probleme, wenn viele Threads laufen. |
AW: Threads (tpIdle) blokieren Anwendung
Zitat:
Ich vermute mal, dass dein Hauptproblem ist, dass die Synchronisationsnachrichten gegenüber den "interaktiven" Nachrichten bevorzugt werden* und schlage folgendes vor:
Ob du das machen willst und dir damit das ganze Synchronisationszeug auf die Seele ziehst, ist natürliche deine Entscheidung :wink: * Kann das jemand bestätigen oder verneinen? Man könnte das ja erstmal in einem Prototyp testen. |
AW: Threads (tpIdle) blokieren Anwendung
Zitat:
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:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:39 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz