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
Seite 1 von 2  1 2      
AJ_Oldendorf

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

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, 15x aufgerufen)
Dateityp: png VCLThread.png (8,1 KB, 8x aufgerufen)
  Mit Zitat antworten Zitat
AJ_Oldendorf

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

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
QuickAndDirty

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

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

  Alt 20. Mai 2025, 12:29
Wo findet das "Protokolieren " statt?
Ist das eine Festplatte? oder eine andere Sequenzielle Systemresource? Vielleicht ein Bereich der durch einen Monitor, eine CS oder eine Mutex geschützt ist?
Du musst die Sachen die im Nebenthread passieren woanders protokolieren als die Sachen die im Hauptthread passieren, wenn das Protokoll die Nebenläufigkeit nicht behindern soll.

Das ist dir klar oder?

Wenn du Nebenläufigkeit haben willst dürfen keine gemeinsamen Variablen oder Resourcen(Festplatte, Systembus, Schnittstelle, Systemhandle) genutzt werden. Es sei denn es ist dir egal wenn alle Threads die diese Resource benutzen jeweils warten bis sie benutztbar ist.
Andreas
Nobody goes there anymore. It's too crowded!

Geändert von QuickAndDirty (20. Mai 2025 um 12:35 Uhr)
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.239 Beiträge
 
Delphi 12 Athens
 
#4

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

  Alt 20. Mai 2025, 12:44
TL;DR;
Schonmal TStopwatch ausprobiert?
https://docwiki.embarcadero.com/Libr...ics.TStopwatch
  Mit Zitat antworten Zitat
AJ_Oldendorf

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

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

  Alt 20. Mai 2025, 12:51
TL;DR; ?

Ich habe auch schon TStopwatch probiert. Kommt zum gleichen Ergebnis wie GetTickCount.

Zum Thema Protokollierung:
Die sieht etwa so aus:

Delphi-Quellcode:
procedure MyProto(aValue: DWord; aAufrufer : String);
begin
  if aValue >= 200 then //=200ms
  begin
    tmpStr := aAufrufer + ' - Value: ' + aValue.ToString;

    //Senden des Strings an den Protokoll-Thread, welcher für das Schreiben zuständig ist
    //PostThreadMessage zum Protokoll-Thread
  end;
end;
Die Protokollierung ist sicherlich nicht das Problem. Die Funktion wird sowohl für die Protokollierung von TC2 als auch TC4 benutzt, natürlich immer mit dem entsprechenden Übergabewert als Value und Aufrufer-String
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.239 Beiträge
 
Delphi 12 Athens
 
#6

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

  Alt 20. Mai 2025, 13:00
Too long thread, didn't read ... (completely)



Ich habe auch schon TStopwatch probiert. Kommt zum gleichen Ergebnis wie GetTickCount.
Ich meinte insbesondere diese Option, statt GetTickCount

class property IsHighResolution: Boolean read FIsHighResolution; Die sollte dann einen HighResolution Timer nehmen, wenn auf True.
Ist womöglich weniger anfällig für Hänger, was noch zu beweisen wäre ...
  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 20. Mai 2025, 13:34
IsHighResolution ist True.
TStopWatch liefert trotzdem ein ähnliches Ergebnis. Muss ich noch was umstellen bei TStopwatch?

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;

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

  t1 := sw.ElapsedMilliseconds;
  //Protokollierung von t1 ...
end;
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
456 Beiträge
 
#8

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.164 Beiträge
 
Delphi 10.3 Rio
 
#9

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
AJ_Oldendorf

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

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

  Alt 22. Mai 2025, 11:52
Danke für die Tips.
Das WaitForsingleObject war ja ein Fehler, es wird ja so gemacht:

Delphi-Quellcode:
while not Terminated do
begin

  Return := MsgWaitForMultipleObjects (Handles, HandleBuffer, False, 251, QS_ALLINPUT);

  //case Return do
  //WAIT_OBJECT_0
  //WAIT_OBJECT_0+Handles
  // : begin
  // while PeekMessage(MessageData, 0, 0, 0, PM_REMOVE) do
  // begin
  // Mach irgendwas mit der Nachricht...
  // end;
  // end;
  //WAIT_TIMEOUT
  //end;

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

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

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

  TC2 := GetTickCount - TC;
  //Protokollierung von TC2 ...
end ;
Das ist aber nur der Thread, der die Daten am Ende verarbeitet. Nicht der UDP Empfang oder Sender Thread...

Hat jemand mal ein Beispiel für Daten, die in eine Threadliste von einem Thread X geschrieben werden und von einem Thread y gelesen werden?
Ich möchte aber den Thread y auch per Message oder Event über bestimmte Dinge informieren können von außen.
Also ein Beispiel mit threadsichere Queue/Liste UND Event.

Dann kann ich das gerne mal versuchen, habe damit noch nichts zu tun gehabt
  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 03:13 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