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 23. Mai 2025
Antwort Antwort
Seite 1 von 2  1 2      
AJ_Oldendorf

Registriert seit: 12. Jun 2009
473 Beiträge
 
Delphi 12 Athens
 
#1

Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 20. Mai 2025, 09:37
Hallo zusammen,
ich habe versucht den Titel auf das nötigste zu reduzieren.
Folgender Fall:

Ich habe ganz viele Threads, welche früher über Synchronize jeweile eine eigene "zeitaufwändige" Funktion aufgerufen haben.
Ich wollte, das die VCL nicht mehr hängt, auf Queue umstellen und habe vor und nach dem Synchronize eine Zeitmessung eingebaut

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?
Hat jemand dazu eine Idee?
Kann der Thread durch irgendwas "blockiert" sein und wenn ja, wie bekomme ich raus, durch was?

Ich hoffe, ihr habt dazu eine Idee
  Mit Zitat antworten Zitat
shebang

Registriert seit: 7. Feb 2020
147 Beiträge
 
Delphi 11 Alexandria
 
#2

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

  Alt 20. Mai 2025, 09:49
Ich wollte, das die VCL nicht mehr hängt, auf Queue umstellen und habe vor und nach dem Synchronize eine Zeitmessung eingebaut
Das Queue ändert ja nichts daran, dass der Code weiterhin vom Hauptthread ausgeführt wird. Es wird nur nicht mehr sofort ausgeführt, sondern asynchron.

Kann es denn passieren, dass die gesamte Funktion inkl Zeitmessung auch mal vom Hauptthread direkt ausgeführt wird? In dem Fall entspricht das Queue nämlich einem Synchronize und du könntest stattdessen ForceQueue verwenden.
  Mit Zitat antworten Zitat
AJ_Oldendorf

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

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

  Alt 20. Mai 2025, 09:55
Nein, der Source oben ist im Execute-Teil des Threads.

Was komisch ist, innerhalb der Funktion "MeineFunktion" habe ich auch eine Zeitmessung, die aber nicht zuschlägt. Das verstehe ich noch nicht wirklich...
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
431 Beiträge
 
#4

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

  Alt 20. Mai 2025, 10:15
Just use a profiler and it will log the blocking method/function/operation, then track the call stack to get better understand how landed here and what it is waiting for.

I think any profiler will do, for my self and as daily driver i use NQS Method Timer from https://nexusdb.com/support/index.php?q=qualitysuite it is fast enough and accurate enough for me, also my license is expired years back and still using it and happy with it, will update when they fix the bugs annoying me the most, there is few, but generally it just works and ideal for a case like yours.

In other words wear investigator hat and think outside the box, you did not mention essential stuff like:
1) if the CPU is being used at that moment or not, like a core at full cycle rotating or not
2) Use Process Explorer or Process Hacker and watch the threads tab, what is going there, do you have rouge thread(s) triggering cosmic number of context switches or not
3) Is the UI responsive or not, can you increase the effect to longer period like 10 seconds and see if Windows mark the UI as non responsive,
4) Also important question, do you use Applicatio.ProcessMessages ?
5) Is there silent exceptions
6) What did you described might have similarity when a loop namely While..do or repeat until lost its bound and went full 32bit, but this can be easy to catch with high CPU usage.
....

And good luck !
Kas
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
473 Beiträge
 
Delphi 12 Athens
 
#5

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

  Alt 20. Mai 2025, 12:11
Hi Kas Ob.,
ich werde mir den Profiler angucken, danke für den Tip.

Zu deinen Fragen:
1) Die CPU Auslastung ist die gesamte Zeit <2%. Auch zu dem Zeitpunkt, wo das Problem auftritt.
2) Im Prozess Explorer sieht man zum Zeitpunkt des Problems, dass einige Threads rot markiert werden. Ich denke, dass bedeutet, dass diese Threads hängen.
Im Anhang auch 2 Bilder. Einmal vom VCL Thread und einmal von der Anwendung selber (ja es sind verdammt viele Threads, es ist auch eine große Anwendung)
3) Die Oberfläche des Programmes lässt sich wirklich nicht bedienen für ca 4-5s. Das Problem kann ich reproduzieren in meiner Anwendung allerdings dauert es nie länger als 5s.
4) Ich benutze Application.ProcessMessages nicht
5) Es gibt einige Stellen im Programm, wo Exceptions abgefangen und behandelt werden
6) CPU Auslastung ist keine vorhanden

Für mich sieht es so aus, dass die besagten Threads in dem Moment keine Rechenzeit erhalten. Eine CPU Auslastung kann ich aber nicht feststellen.

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
  TC := GetTickCount;

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

  TC2 := GetTickCount - TC;
  //Protokollierung von TC2...
end;
So sieht das ganze grob aus.

Die Funktion "MeineFunktion" sieht etwa so aus:

Delphi-Quellcode:
procedure MeineFunktion;
begin
  var TC3 : DWORD;
  var TC4 : DWORD;
  
  TC3 := GetTickCount;
  //Mache irgendwas zeitaufwändiges

  TC4 := GetTickCount - TC3;
  //Protokollierung von TC4...
end;
Verwundert bin ich nur, dass die Protokollierung von TC2 zuschlägt, allerdings von TC4 nicht. (zur Info, die Protokollierung erfolgt nur, wenn der Wert >200ms ist)
Angehängte Grafiken
Dateityp: png Anwendung.png (20,3 KB, 14x aufgerufen)
Dateityp: png VCLThread.png (8,1 KB, 8x aufgerufen)
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
473 Beiträge
 
Delphi 12 Athens
 
#6

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

  Alt 20. Mai 2025, 12:22
auch mit ForceQueue, erfolgt die Protokollierung von TC2 aber innerhalb der Funktion, schlägt keine Protokollierung von TC4 zu. VCL hängt auch.

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
  TC := GetTickCount;

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

  TC2 := GetTickCount - TC;
  //Protokollierung von TC2...
end;
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
431 Beiträge
 
#7

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

  Alt 20. Mai 2025, 17:14
There is good advices above, and here what i see
1) according to screenshot, your main thread is spending in kernel time 4 times more than user time, that way more than usual or accepted and this is the cause.
2) saying you see red in CPU usage, meaning the threads are spedning too much time and also invoking system calls (not system functions), and/or too much IO operations.
3) This bring me to ask how many Threads are you creating and destroying per second ?
4) How many IO operation are you issueing per second ?
5) you mentioned UDP above, i might missed something, but if this is server, are you polling the status like that code above? i mean perform select over 250ms then loop back ? how many threads are doing this?
6) I have problem with this "if WaitForsingleObject(Something, 250, xxxx) = WAIT_OBJECT_0 do" in what thread it being used, also one thread or more? like 64 ?
7) Are these TC1,TC2,TC3,TCx... local variables ? i mean all, or some of them are accessible and writable by multiple thread, when i see stuff like this "TC2 := GetTickCount - TC;" this should not be used out side the scope of this thread, example how this can go wrong, two threads calling GetTickCount each within interval supposed to be 250ms, you assume the difference between their result will be within 250ms, in real life the difference can be 5 seconds (5000ms)! or even more, you have no control over this.
8) also as (7) and even more important if one thread performed an action and in the last stage updated some checkpoint timer lets say grabbed GetTickCount, then signaled for finish, if you are signaling before grabbing the time, then this thread might block for more time the next, then update the time indicator send the next thread in waiting state because code like this "TC2 := GetTickCount - TC;" if TC is not local and only limited to this thread then it easily can be negative value, be extra careful here.


Now to most important quesitons,
what are the operations these threads are doing ?
writing files or sending/recv packets ?
and why there is this very short period 250ms anywhere in your code ? this is not a joke and easily can go from speed enhancer to speed killer.

no matter what is the operation, then you must remove the dependency on time and switch to operation completion, in other words the fact you depend on GetTickCount to time or singal your threads to work, indicate critical problem in and design shortcoming.
Kas
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.155 Beiträge
 
Delphi 10.3 Rio
 
#8

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

  Alt 22. Mai 2025, 11:40
Also...

Hier gibt es ja schon viele Fragen und Antworten... Aber.

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
  TC := GetTickCount;

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

  TC2 := GetTickCount - TC;
  //Protokollierung von TC2...
end;

Das ist natürlich der klassische Fehler für die Verwendung eines Threads (Übrings genau das behandle ich in meinem Talk in Amsterdam).

In einem Thread Queue aufzurufen ist natürlich nicht das Problem, aber nur um "Kleinigkeiten" auf der UI darzustellen. Die eigentliche Verarbeitung muss im Thread passieren.

WaitForsingleObject kann man nehmen, aber ich würde ein TEvent verwenden.

Da der Server ja immer nur eine Datenpacket nach dem anderen Empfängt würde ich die Aufgabe nicht an N-Thread pro N-Client weiter geben sondern das Datenpacket in eine Threadsichere Quere packen, die von X-Threads abgearbeitet werden.

Nur so ein paar gedanken.

Mavarik
  Mit Zitat antworten Zitat
QuickAndDirty

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

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

  Alt 20. Mai 2025, 12:04
Nein, der Source oben ist im Execute-Teil des Threads.
Synchronize, Queue und ForceQueue
Führen code im Hauptthread aus.

In windows: Synchronize udn Queue führen den code "sofort" im Hauptthread aus. ForceQueue setzt die Ausführung des Codes ans Ande der MessageQueue und führt den Code aus kurz bevor Application.OnIdle passiert.

Ich habe außerdem festgestellt, dass Application.processmessages nicht gut mit Multithreading und Synchronization und warten und blockieren USW. zusammenspielt... also am Besten nie Application.processmessages nutzen.

Am besten immer GetTickCount64 benutzen GitTickCount ist deprecated. Bei so kleinen workloads (null workload) vieleicht sogar nen HighperformanceCounter nutzen...
Andreas
Monads? Wtf are Monads?

Geändert von QuickAndDirty (20. Mai 2025 um 12:14 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

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

  Alt 20. Mai 2025, 16:41
Suspend sollte NIEMALS verwendet werden
(OK, ein Thread sich selbst geht, aber auch da gibt es Besseres,
und von außerhalb ist es einfach nur gefährlich, da nicht bestimmt werden kann, ob an aktueller Stelle angehalten werden darf)

z.B. es wird grade ein String kopiert oder eine Speicheranforderung (delphis Speichermanager/FastMM) abgearbeitet
oder der Code ist grad in einer Sperre (CritticalSection oder so) drin, dann kannst du damit das komplette Programm (andere Threads) blockieren.

Andersrum kann ein Thread auch so blockiert werden (ohne ihn selbst anzuhalten) ... z.B. CriticalSections und Dergleichen.


Ob jetzt TStopwatch oder GetTickCount ist auch egal.
TStopwatch bietet ein paar nette Features und ist genauer.
GetTickCount hat auf vielen Systemen standardmäßig eine Auflösung von etwa 16 Millisekunden. (Kürzeres kann nicht gemessen werden und ist immer 0 und längeres wird gerundet)


Ich wollte, das die VCL nicht mehr hängt, auf Queue umstellen und habe vor und nach dem Synchronize eine Zeitmessung eingebaut
Sowohl beim Synchronize, als auch beim Queue wird der Code (Funktion) im Hauptthread ausgeführt.
Für den Hauptthread macht es also keinen Unterschied,

außer dass beim Queue die Funktion nicht sofort, sondern erst später ausgeführt wird.
(Ausnahme, das Queue wird innerhalb des Hauptthreads ausgeführt, dann macht der Schrott nicht das, wonach es klingt, sondern führt es sofort aus, genauso wie beim Synchronize)
Bugfix: einfach immer ForceQueue statt Queue verwenden, das ist wirklich immer verzögert.

Ausnahme, der Hauptthread wartet auf diesen Thread (WaitFor oder sonstwas) oder auf etwas Anderes
und der Thread will ein Synchronize machen, wodurch er auf den Hautthread wartet (bis jener diese Funktion fertig ausgeführt hat),
aber da der Hauptthread wartet, kommt er nicht dazu das zu machen und beide warten bis in alle Ewigkeit.



Beim Queue ist die Zeitmessung aber auch bissl nutzlos, da es dort nur das Eintragen in die Liste misst, aber nicht die Funktion.
Wenn, dann innerhalb der Funktion messen.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (20. Mai 2025 um 16:46 Uhr)
  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 15:22 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