AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Thread.Queue, Zeitmessung, Thread hängt angeblich
Thema durchsuchen
Ansicht
Themen-Optionen

Thread.Queue, Zeitmessung, Thread hängt angeblich

Ein Thema von AJ_Oldendorf · begonnen am 20. Mai 2025 · letzter Beitrag vom 26. Mai 2025
Antwort Antwort
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.750 Beiträge
 
Delphi 12 Athens
 
#1

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 20. Mai 2025, 16:55
Beim Queue ist die Zeitmessung aber auch bissl nutzlos, da es dort nur das Eintragen in die Liste misst, aber nicht die Funktion.
Wenn ich das richtig verstanden habe, ist aber genau das das Problem:

Delphi-Quellcode:
TC := GetTickCount;

//Synchronize(MeineFunktion);
Queue(Nil, MeineFunktion);

TC2 := GetTickCount - TC;
//Protokollierung von TC2...
TC2 ist teilweise 500ms.
Unter Synchronize verstehe ich das ja, aber wieso bei Queue auch?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.531 Beiträge
 
Delphi 12 Athens
 
#2

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 20. Mai 2025, 18:02
Wenn ich das richtig verstanden habe, ist aber genau das das Problem:
Bei Diesem sollte der Lock aber nicht lange dauern und es nahezu sofort zurückkehren.

Einzig mir bekannte Ausnahme ist eben, wenn Queue aus dem Hauptthread aufgerufen wird, wodurch es fast wie Synchronize wirkt (die Funktion wird direkt aufgerufen, ohne in der Queue zu landen).
Oder wenn jemand es geschafft hat den Speicher zu schrotten (BufferOverflow, mistige Zeiger und Dergleichen), aber dann hat man eh andere Probleme, als nur dieses Hängen.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
486 Beiträge
 
Delphi 12 Athens
 
#3

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 21. Mai 2025, 05:47
Guten Morgen,
also nochmal grob erklärt und zusammengefasst:
Es sind ca 35 UDP Teilnehmer an der Anwendung angemeldet (die Anwendung ist ein UDP Server und empfängt die Daten im OnUDPRead Event der Indy Komponente). Jeder UDP Teilnehmer ist ein eigener Thread da dieser losgelöst kommunizieren kann von den anderen.
Meine Threadinstanz, wo ich das Problem mit der Zeitmessung habe, bekommt die Daten von dem jeweiligen UDP Thread geschickt via "PostThreadMessage".

Diese Threadinstanz (existiert also auch 35x, da 35 UDP Teilnehmer online sind), empfängt die Daten in ihrer ThreadQueue grob durch folgenden Aufruf:

Delphi-Quellcode:
while not Terminated do
begin

  //hier erfolgt eine Signalisierung über WaitForSingleObject und bei Timeout (=250ms), erfolgt der zyklische Aufruf unten
  if WaitForsingleObject(Irgendwas, 250, xxxx) = WAIT_OBJECT_0 do
  begin

  end;

  //zyklischer Aufruf
  var sw := TStopwatch.StartNew;
  var TC : DWORD;
  TC := GetTickCount;

  //Synchronize(MeineFunktion);
  //Queue(Nil, MeineFunktion);
  //ForceQueue(Nil, MeineFunktion);

  t1 := sw.ElapsedMilliseconds;
  //Protokollierung von t1 ...

  TC2 := GetTickCount - TC;
  //Protokollierung von TC2 ...
end;
Die Protokollierung der Zeitmessung sowohl von t1 als auch TC2, schlägt zu. Egal welcher der 3 Aufrufe genutzt wird.
Eine Prüfung vorher auf if (MainThreadID <> GetCurrentThreadID) then zeigt auch, dass es nicht der VCL Thread ist als Aufrufer.
Die Protokollierung innerhalb der Funktion "MeineFunktion" schlägt nicht zu.

Ich muss weitere Untersuchungen anstellen, da auch ein Ausklammern der Funktion "MeineFunktion" dazu führt, dass die VCL hängt. Synchronize Aufrufe habe ich keine mehr im Programm. Ich muss prüfen, wer die VCL blockiert. Eurekalog habe ich schon mal installiert aber bei HangDetection wurde mir nichts angezeigt bzw. wann wird da wo was angezeigt? In dem Moment wo die Anwendung hängt oder beim Beenden?
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
486 Beiträge
 
Delphi 12 Athens
 
#4

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 21. Mai 2025, 07:14
Edit:
Habe mir das OnIdle Event der Anwendung mal protokolliert und das kommt 7s nicht, genau in dem Zeitraum, wo die VCL auch hängt
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
2.052 Beiträge
 
Delphi 12 Athens
 
#5

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 21. Mai 2025, 08:37
Was passiert wenn du mehr "PostThreadMessage" ausführst als in den 35 threads und dem Protocoll thread und dem Hauptthread ausgefürht werden können?
Gibt es ein Maximum and Queue size? Oder ist die Queue irgendwann Greedy und will abgearbeitet werden bevor neue Messages auflaufen?
Gibt es da einen Mechanismus in der Art der zum tragen kommen könnte?

Was wenn du von Threads auf Tasks(ITask) umsteigst, oder ist da kein effizenz Gewinn möglich da du eh schon mit nem Threadpools arbeitest?
Andreas
Nobody goes there anymore. It's too crowded!
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
455 Beiträge
 
#6

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 21. Mai 2025, 09:00
Now i am more confused than before, sorry.

You did not explain what is going on, as you still abusing Indy and its threads !

1) Your server is using multithread to handle UDP connections, that is fine and is in fact the right way, BUT as you did again miss the explaining what exactly and how you handle these received UDP packets, i will assume you are handling them all in the main thread and enforcing this by these
Delphi-Quellcode:
  //Synchronize(MeineFunktion);
  //Queue(Nil, MeineFunktion);
  //ForceQueue(Nil, MeineFunktion);
Congratulations, you defeated the whole purpose of using multithread server to handle connections, and you are better to switch to event based server and handle everything in the main thread.
The whole approach of using or receiving packets and handling in the main thread, is to not block packet handling and absolve the main thread to handle UI.
But this is based on what i see from the code you pasted, the same code without more details, like where the UDP packers read is happening.

2) What on earth this WaitForsingleObject is used for ?, what the idea of it ? purpose ? and it is inside the thread execution loop ? that can't be more wrong on so many level, it is like you have one wheel but only interacting with it with stick(s).

3) You confirming the TC, yet i still see TC2, and don't see where these variables declared are they all local to this thread ? how are you logging ?

4) you mentioned PostThreadMessage, how this fit in all of this, you either use PostThreadMessage or one of these
Delphi-Quellcode:
  //Synchronize(MeineFunktion);
  //Queue(Nil, MeineFunktion);
  //ForceQueue(Nil, MeineFunktion);
never together, well you can, but nothing good is coming out of it.

5) OnIdle is taking 7 seconds, is clear evidence of you killing the main thread, now you said the CPU is not high or no CPU usage, so let me explain how modern CPU(s) work, one thread will run on one core at any moment, so main thread is hugged or and on full job, then one core will go 100%, if you look on you overall CPUusage and it is 4 cores, then it will show 25%, if you CPU 8 then it will show %12 ....
So look again how much your main thread is utilizing.

6) THe fact Process Explorer showing too much red, and from your screenshot, i pointed that kernel time is multiple over user time, is clear that main thread is put to handle IO or something has to do with kernel operation, what is it ?

Here an example on how to handle UDP, it is this simple and don't complicate things, https://stackoverflow.com/questions/...simple-strings

Know this : You can receive thousands of packets of hundreds clients per seconds on main thread and it will not glitch for fraction of seconds, as you don't handle or process these packets just receive, so either receive everything in main thread then signal few threads to process, or receive in background thread and handle them there, never in main thread.

Main thread is not super thread or faster than any other threads, on contrary it is burdened with UI handling, so less job for it,

ps :
7) are you logging in main thread ? how many operation per second ? also how many packets you do receive per seconds ?
Kas
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
486 Beiträge
 
Delphi 12 Athens
 
#7

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 21. Mai 2025, 09:56
PostThreadMessage wird sicherlich noch an anderen Stellen aufgerufen, da dies ja eine Nachricht an ein bestimmten Thread ist (mit Angabe des ThreadHandles wird PostThreadMessage aufgerufen).

ITask habe ich noch nie benutzt und wüsste jetzt auch nicht, warum man das umstellen sollte?! Vor- und Nachteile?

@Kas Ob.
Ich versuche nur auf ein Bruchteil zu antworten, da meiner Meinung nach Fragen dabei sind, die nichts damit zu tun haben.

Die IdUDPServer Komponente ruft das OnUDPRead Event auf. Dort werden die Nachrichten an die entsprechenden Clients-Threads weitergeleitet.
Der Aufruf des OnUDPRead Events erfolgt NICHT in der VCL.
Geprüft durch Abfrage if (MainThreadID <> GetCurrentThreadID) then Die Threads empfangen die Nachrichten und machen damit etwas.
Auf das erfolgt nicht in der VCL.

Ich sage auch nicht, dass es am UDP hängt! Ich bekomme es nur damit nachgestellt. Es hängt definitiv die VCL (siehe IdleEvent). Eventuell ist auch etwas anderes Schuld. Synchronize Aufrufe sind KEINE im Programm.
CPU Auslastung vom MainThread ist laut Prozessexplorer 0.05, während die Anwendung hängt!
Mein Rechner hat 24 Kerne, eine volle Auslastung wären demnach 4%, welche ich aber NICHT habe.

Kleine Korrektur, es ist nicht "WaitForsingleObject" sondern "MsgWaitForMultipleObjects".
Wenn der Returnwert = WAIT_OBJECT_0 ist, wird die Thread-Queue abgearbeitet mit while PeekMessage(MessageData, 0, 0, 0, PM_REMOVE) do Ja, alle Variablen für die Zeitmessung sind lokal. Ich hatte TC2 vergessen mit in dem Codeschnipsel zu schreiben. Ist ja nur ein Ausschnitt des Codes und da hatte ich TC2 übersehen.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.531 Beiträge
 
Delphi 12 Athens
 
#8

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 21. Mai 2025, 10:30
Die ThreadQueue hat ein Limit (keine Ahnung wie groß)
und wenn voll, dann wird beim PostThreadMessage/PostMessage/SendMessage die Eintragung verworfen und diese Funktionen geben einen Fehlercode zurück.

Jeder Thread hat seine eigene Queue, welche beim ersten Zugriff erzeugt wird.
Statt einer GDI-Queue könnte man z.B. eine TThreadList verwenden. (bzw. es gibt auch irgendwo threadsichere TQueueIrgendwas und TStackIrgendwas im Delphi)
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
455 Beiträge
 
#9

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 21. Mai 2025, 10:52
PostThreadMessage wird sicherlich noch an anderen Stellen aufgerufen, da dies ja eine Nachricht an ein bestimmten Thread ist (mit Angabe des ThreadHandles wird PostThreadMessage aufgerufen).

ITask habe ich noch nie benutzt und wüsste jetzt auch nicht, warum man das umstellen sollte?! Vor- und Nachteile?

@Kas Ob.
Ich versuche nur auf ein Bruchteil zu antworten, da meiner Meinung nach Fragen dabei sind, die nichts damit zu tun haben.

Die IdUDPServer Komponente ruft das OnUDPRead Event auf. Dort werden die Nachrichten an die entsprechenden Clients-Threads weitergeleitet.
Der Aufruf des OnUDPRead Events erfolgt NICHT in der VCL.
Geprüft durch Abfrage if (MainThreadID <> GetCurrentThreadID) then Die Threads empfangen die Nachrichten und machen damit etwas.
Auf das erfolgt nicht in der VCL.

Ich sage auch nicht, dass es am UDP hängt! Ich bekomme es nur damit nachgestellt. Es hängt definitiv die VCL (siehe IdleEvent). Eventuell ist auch etwas anderes Schuld. Synchronize Aufrufe sind KEINE im Programm.
CPU Auslastung vom MainThread ist laut Prozessexplorer 0.05, während die Anwendung hängt!
Mein Rechner hat 24 Kerne, eine volle Auslastung wären demnach 4%, welche ich aber NICHT habe.

Kleine Korrektur, es ist nicht "WaitForsingleObject" sondern "MsgWaitForMultipleObjects".
Wenn der Returnwert = WAIT_OBJECT_0 ist, wird die Thread-Queue abgearbeitet mit while PeekMessage(MessageData, 0, 0, 0, PM_REMOVE) do Ja, alle Variablen für die Zeitmessung sind lokal. Ich hatte TC2 vergessen mit in dem Codeschnipsel zu schreiben. Ist ja nur ein Ausschnitt des Codes und da hatte ich TC2 übersehen.
Now this is confusing even more,

If you are using OnUDPRead and it is running in background thread context then what this loop suppose to serve ?
Delphi-Quellcode:
while not Terminated do
begin

  //here a signal is sent via WaitForSingleObject and if the timeout occurs (=250ms), the cyclic call below is made
  if WaitForsingleObject(Something, 250, xxxx) = WAIT_OBJECT_0 do
  begin

  end ;

end ;
Where is running ? and it is hugging something and should be removed, yes altogether, remove it.

Just take a step back and look at the big picture and simplify the whole thing, and don't answer my question, and trying to explain to me, and yes, imagine you are trying to explain the whole thing and i am %100 sure you will figure the miss use of over engineering you are doing.

here a simple approach :
OnUDPRead fired, we read, we are in background thread so no synchronization call of any sort is needed, we process and we exit, no looping no waiting for msg or anything inside these events. you need to log something then use a faster approach and don't want on disk or UI updates, use PostMessage and that is it.
Kas
  Mit Zitat antworten Zitat
Antwort Antwort


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 22:30 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