Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Vorgehensweise Threads + TIdTCPClient (https://www.delphipraxis.net/206779-vorgehensweise-threads-tidtcpclient.html)

frasch75 28. Jan 2021 17:20

Vorgehensweise Threads + TIdTCPClient
 
Hallo,
habe bislang mit threads noch nichts programmiert, deshalb suche ich mal Anregungen zur möglichen Vorgehensweise im konkreten Fall. Ich hoffe ich kann mich halbwegs verständlich ausdrücken.

Ich habe eine Anwendung mit Tages-Kalender (ähnlich wie Outlook, allerdings 1min Stufung), der auch alle 60s aktualisiert werden soll. Bedeutet u.a., dass die Zeitskala jede Minute nach oben rutscht. Außerdem wird die aktuelle Anwendungszeit (nicht identisch mit realer Zeit) in der Statuszeile angezeigt.

Die Einträge für den Kalender kommen aus TLists. Diese werden periodisch (derzeit noch seriell) durch xml-Abfragen über den TCPClient gefüllt. Dabei habe ich zuerst eine primäre Abfrage, und dann zwei Detailabfragen, die sich auf IDs aus der Primärabfrage beziehen (unterschiedliche xml-Anfragen, lassen sich also nicht zusammenfassen).

Bei kleineren Umgebungen funktioniert das (wie immer) auch sehr gut. Bei größeren dauern die Abfragen und das anschließende Parsen (und notwendige Manipulieren) der xml-Ergebnisse mit zunehmender Laufzeit jedoch immer länger (es werden halt immer längere Listen, die abzuarbeiten sind). Dadurch hängt in der Zwischenzeit die Aktualisierung des Kalenders (tw. 3-4min, hohe CPU-Last).

Nun habe ich die Idee, alle 3 Abfragen in threads auszulagern, damit der Kalender trotzdem aktualisiert werden kann. Zudem könnten aus meiner Sicht die beiden Detailabfragen parallel erfolgen und geparst werden. Also zuerst ein Primär-Thread, und wenn der beendet ist dann parallel 2 Sekundärthreads. Wenn die Abfragen alle durch sind, z.B. 30s warten, dann das ganze von vorne.

Denkt Ihr, dass das eine mögliche Vorgehensweise wäre? Müsste ich dann mehrere TCPClients definieren? Hierbei gibt es noch das Problem (?), dass ich mich erst beim Server registrieren muss (auch per xml-API), bevor er mir irgendwelche Daten liefert.
Es geht mir hier eher um grundsätzliche Ansätze als konkrete Umsetzungen; das wäre dann eh meine Hausaufgabe ;-)

Vielen Dank
Frank.

himitsu 28. Jan 2021 18:13

AW: Vorgehensweise Threads + TIdTCPClient
 
Pro Thread ein TCPClient.
Ansonsten müsstes du die Zugriffe wieder synchronisieren, womit es dann wieder nacheinander abgeht.

Aber die TCP-Abfragen selber sollten doch nicht so lange dauern?
Somit kannst die alle 3 in einem Thread laufen lassen.

Außerdem kannst die Threads nach der Abfrage weiterlaufen lassen. (das starten und beenden von Threads verbraucht eine "Menge" Zeit)
Das könnte man eventuell über Fiber, bzw. TTask/TFuture beheben. (da laufen mehrere Fibers/Tasks nacheinander im selben Thread, bzw. in einem ThreadPool)

z.B.
  • ein Thread macht alle 60 Sekunden die TCP-Abfragen
    • und eventuell auch gleich das Parsen der XML (sollte eigentlich auch schnell gehn)
    • TCPClient und XML-Klassen bleiben bestehen und werden im nächsten Durchlauf gleich wiederverwendet ... bräuchte dann vermutlich auch nur einmal die "Anmeldung" (vielleicht nach xxx Minuten nochmal erneut, falls es eine MaxLifeTime für die Anmeldung gibt)
  • das Ergebnis davon wird dann an einen weiteren Thread übergeben, welcher das in die Liste einträgt und sonstwas Zeitaufwändiges macht (falls die Liste Threadsave ist, können das auch mehrere Threads parallel machen)
    • falls das Eintragen in die Liste es erlaubt "mehrere" Datensätze "schneller" zusammen zu verarbeiten, dann kann der Abfrage-Thread seine Ergebnisse in eine Liste Eintragen, wo der ArbeitsThread dann einen/mehrere vorhandene Einträge sich rausholt (z.B. wenn eine Berechnung mal länger als 60 Sekunden brauchte, dann sind im nächsten Durchlauf ja auch mehrere neue Daten reingekommen)
  • und am Ende gibt es ein Synchronize oder Queue, welches die fertige Berechnung nur noch "schnell" in die GUI einträgt (nur hier hängt dann mal ganz kurz der Hauptthread)
    • alternativ auch als Event, wo der Arbeitsthread seine Ergebnisse in eine Liste einträgt und sich durch das Ebent angestoßen der dann in einem Rutsch einen/mehrere Ergebnisse zusammen in die GUI einträgt (falls die GUI mal hing)

frasch75 29. Jan 2021 16:57

AW: Vorgehensweise Threads + TIdTCPClient
 
Vielen Dank für die ausführliche Antwort. Die hat dann gleich mehrere "Anschubser" bewirkt...

Die bisherige Programmversion war wohl mehr eine schnell hingeschluderte Variante, die im Grundsatz macht was sie soll, aber halt ihre Performancegrenzen hat.

Nun geht es halt an die schrittweise Optimierung incl. Prüfung auf Thread-Möglichkeiten:
- Optimierung der xml-Abfragen an sich (Ergebnis geht bislang zeilenweise in eine StringList)
- anschließendes xml-Parsing in eine Datenstruktur (TList of records)
- und Manipulation der Daten für die endgültige Anzeige (da müssen diverse Flags und Randbedingungen aus den xml-Ergebnissen ausgewertet und in weitere Properties geschrieben werden)
- ...

Wer keine Arbeit hat, macht sich halt welche und der Mensch wächst an seinen Aufgaben ;-)

Vielen Dank nochmals für die Anregungen!

VG Frank.

TurboMagic 30. Jan 2021 12:57

AW: Vorgehensweise Threads + TIdTCPClient
 
Bedeutet dass, dass du das XML Parsen "von Hand" machst?
Es gibt in Delphi nämlich auch XML Parser...

frasch75 30. Jan 2021 15:38

AW: Vorgehensweise Threads + TIdTCPClient
 
ähm, in der ersten Version schon :wall:

Bin jetzt gerade dabei, mir das Grundgerüst für die verbesserte Version zusammenzubasteln. Da soll dann auch das Parsen verbessert werden. Deswegen habe ich die Anregungen gerne aufgenommen, auch wenn das jetzt weit über meine ursprüngliche Anfrage hinausgeht. Aber manchmal sieht man den Wald vor Bäumen nicht...

Die API-Abfragen (xml) werde ich normal ohne separate Threads laufen lassen, das scheint mir nach einem ersten Test recht schnell zu gehen. Da kommen dann neu erstmal nur TStringLists raus. Aber die Performance muss ich mir dann erstmal am Lifesystem anschauen, das Testsystem hat nicht so viele Einträge.
Die TStringLists müssten dann geparst werden, wobei ich noch darüber nachdenke, dann nur die letzten Detailabfragen (die als Parameter eine ID aus der Hauptabfrage benötigen, wozu die allerdings schonmal interpretiert sein muss) in jeweils eigenen Threads laufen zu lassen.

Dann hat sich auch das Thema IdTCPClient i.Z. mit Threads erledigt.

Als Ergebnis des xml-Parsers bräuchte ich dann mehrere TLists of record, die eine Kombination der verschiedenen xml-Felder aus den 3 Abfragen darstellen. Allerdings müssen einige der xml-Felder vorher noch manipuliert und anschließend die TLists aktualisiert werden. Letzteres dürfte nicht so lange dauern, die meiste Zeit werde ich wohl bislang beim Auseinanderpflücken und Umarbeiten der xml-Strings verplempern.

Für die Tests lasse ich erstmal den ganzen GUI-Kram weg, will erstmal sehen, wie dann nach den ganzen Änderungen die gesamte Abfrage-/Bearbeitungsperformace aussieht. In der Zwischenzeit kann ich bei Bedarf ganz gut mit der alten Version arbeiten, so dass auch kein Zeitdruck besteht.

VG
Frank.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:45 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