Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Thread.Queue, Zeitmessung, Thread hängt angeblich (https://www.delphipraxis.net/217196-thread-queue-zeitmessung-thread-haengt-angeblich.html)

AJ_Oldendorf 20. Mai 2025 09:37

Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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

shebang 20. Mai 2025 09:49

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

Zitat von AJ_Oldendorf (Beitrag 1548710)
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.

AJ_Oldendorf 20. Mai 2025 09:55

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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...

Kas Ob. 20. Mai 2025 10:15

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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 !

QuickAndDirty 20. Mai 2025 12:04

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

Zitat von AJ_Oldendorf (Beitrag 1548717)
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...

AJ_Oldendorf 20. Mai 2025 12:11

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Liste der Anhänge anzeigen (Anzahl: 2)
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)

AJ_Oldendorf 20. Mai 2025 12:22

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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;

QuickAndDirty 20. Mai 2025 12:29

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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.

Rollo62 20. Mai 2025 12:44

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
TL;DR;
Schonmal TStopwatch ausprobiert?
https://docwiki.embarcadero.com/Libr...ics.TStopwatch

AJ_Oldendorf 20. Mai 2025 12:51

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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

Rollo62 20. Mai 2025 13:00

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

Zitat von AJ_Oldendorf (Beitrag 1548742)
TL;DR; ?

Too long thread, didn't read ... (completely)



Zitat:

Zitat von AJ_Oldendorf (Beitrag 1548742)
Ich habe auch schon TStopwatch probiert. Kommt zum gleichen Ergebnis wie GetTickCount.

Ich meinte insbesondere diese Option, statt GetTickCount

Delphi-Quellcode:
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 ... :stupid:

AJ_Oldendorf 20. Mai 2025 13:34

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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;

Rollo62 20. Mai 2025 13:56

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Dann hängt der HighResolution Timer wohl genauso.

Könnte es an der Schleife liegen, welche die Queue flutet?
Vielleicht versuchtst Du mal die Sequenz einzeln, ohne Schleife aufzurufen und zu messen,
oder zu versuchen wie oft der in die Queue läuft.

QuickAndDirty 20. Mai 2025 14:02

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Für mich sieht es so aus als ob das Protokoll verantwortlich ist. Auch wenn es mit Metacode und Brotkrumen an achtem Code immer etwas schwer zu verstehen ist...

Führe ein Protokoll für den Nebenthread das nur im Speicher geführt wird und im Nebenthread erzeugt wurde.
Dann übergebe das Protokoll in OnTerminate aus dem NebenThread in dein eigentliches Protokoll.

Nur so kannst du verhindern das ein Thread beim Protokolieren auf den anderen wartet.

AJ_Oldendorf 20. Mai 2025 14:21

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
@QuickAndDirty:
Also, die VCL hängt. Wenn ich keine Protokollierung sondern nur ein Breakpoint auf die Abfrage >=200 mache, kommt er auch rein.
Ob ich es in ein Protokoll schreibe oder nicht, völlig egal. Es wird außerdem in das Protokoll mit "PostThreadMessage" eine Nachricht geschickt. Das führt nicht zu einem VCL Hänger.

Es passiert auch nur unter bestimmten Umständen (ich kann das provozieren).
Wenn alles "normal" läuft, geht der Thread auch durch diese Funktion und nichts wird protokolliert. Es ist also kein generelles Problem der Funktion. Deswegen glaube ich immernoch, dass der Thread "blockiert" bzw keine Rechenzeit mehr bekommt. So sieht es für mich irgendwie aus.

Uwe Raabe 20. Mai 2025 14:39

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Wenn du das provozieren kannst, dann sag doch mal wie. Vielleicht gibt das ja einen Hinweis auf die Ursache.

AJ_Oldendorf 20. Mai 2025 14:48

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
In einem ganz anderen Thread sind ca 35 UDP Teilnehmer mit der Anwendung verbunden und wenn ich ca 10 Teilnehmer (oder auch mehr) die Verbindung trenne, dann passiert es. Aber auch erst zeitverzögert nach einigen Sekunden. Aber der Thread, der anscheinend hängt, hat damit gar nichts zu tun. Daher weiß ich nicht, ob das nur Zufall ist oder irgendwas mit Kontextwechseln zu tun haben könnte.

Ist es denn generell möglich, dass ein Thread, der gerade irgendwo läuft, geblockt wird von außen?
Natürlich ohne das dieser Thread auf irgendwas wartet. Also wie in meinem Beispiel unten, while not Terminated Schleife, Synchronize/Queue/ForceQueue und dann wird er "pausiert" und setzt dann aber genau an der Stelle fort?

Uwe Raabe 20. Mai 2025 15:04

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

Zitat von AJ_Oldendorf (Beitrag 1548757)
Ist es denn generell möglich, dass ein Thread, der gerade irgendwo läuft, geblockt wird von außen?

Na klar, dafür stellt Windows z.B. die Funktion SuspendThread zur Verfügung. Bei MadExcept gibt es auch eine Option pause all running delphi/bcb threads.

QuickAndDirty 20. Mai 2025 16:10

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

Zitat von AJ_Oldendorf (Beitrag 1548753)
Wenn alles "normal" läuft, geht der Thread auch durch diese Funktion und nichts wird protokolliert. Es ist also kein generelles Problem der Funktion. Deswegen glaube ich immernoch, dass der Thread "blockiert" bzw keine Rechenzeit mehr bekommt. So sieht es für mich irgendwie aus.

Interessant.
Ändert die ThreadPriority irgendetwas?
Es ist ja nun schon so, dass realistischer weise von den 200 threads von all den prozessen die laufen nur ein paar wirklich gleichzeitig laufen.
Allerdings weiß ich nicht wie genau sich prozess priorität und thread priorität addieren...multiplizieren...?
Aber da du eh schon alles ausprobiert hast, warum nicht auch thread priority?

Ich frage mich wirklich wie PostThreadMessage die Queue des Threads manipuliert ohne sich mit der MessageLoop des Threads zu synchronisieren. Ich suche ja schon länger nach einer einfachen Lockfree-Queue.

himitsu 20. Mai 2025 16:41

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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)


Zitat:

Zitat von AJ_Oldendorf (Beitrag 1548710)
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.

Uwe Raabe 20. Mai 2025 16:55

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

Zitat von himitsu (Beitrag 1548760)
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:
Zitat:

Zitat von AJ_Oldendorf (Beitrag 1548710)

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?


Kas Ob. 20. Mai 2025 17:14

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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.

himitsu 20. Mai 2025 18:02

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

Zitat von Uwe Raabe (Beitrag 1548761)
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.

AJ_Oldendorf 21. Mai 2025 05:47

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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
Delphi-Quellcode:
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?

AJ_Oldendorf 21. Mai 2025 07:14

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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

QuickAndDirty 21. Mai 2025 08:37

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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?

Kas Ob. 21. Mai 2025 09:00

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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 ?

AJ_Oldendorf 21. Mai 2025 09:56

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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
Delphi-Quellcode:
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
Delphi-Quellcode:
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.

himitsu 21. Mai 2025 10:30

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
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)

AJ_Oldendorf 21. Mai 2025 10:51

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
PostThreadMessage habe ich immer auf das Result abgefragt und dies ist nie False, also immer erfolgreich gewesen.

Hier auch nochmal als Beweis eine Protokollierung im OnUDPRead Event:

AThread.ThreadID: 30856
MainThreadID: 32612
GetCurrentThreadID: 30856

Also wird es nicht im Hauptthread empfangen und verarbeitet

Kas Ob. 21. Mai 2025 10:52

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

Zitat von AJ_Oldendorf (Beitrag 1548783)
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
Delphi-Quellcode:
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
Delphi-Quellcode:
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.

AJ_Oldendorf 21. Mai 2025 11:14

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Ich versuche es nochmal zu erklären.

Threadübersicht:
UDPServer Anzahl 1 = Thread Nummer 1
UDPClient Anzahl 1..35 = Thread Nummer 2..36
Verarbeitungsthread Anzahl 1..35 = Thread Nummer 37..71
weitere Threads, die für andere Funktionen zuständig sind, allerdings den Verarbeitungsthreads 37..71 auch Nachrichten schicken können.

UDPServer gibt die empfangenen Daten an den UDPClient weiter, via PostThreadMessage
UDPClient gibt Daten nach Prüfung und Validierung und anderen Dingen, an den Verarbeitungsthread weiter, via PostThreadMessage

Verabreitungsthread sieht ungefähr so aus:

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 ;
Wie gesagt, nur ein grober Auszug...

AJ_Oldendorf 21. Mai 2025 11:26

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Das Verhalten mit dem VCL Hänger scheint genau dann aufzutreten, wenn ich gleichzeitig die Verbindung zu allen 35 UDP Teilnehmern trenne (Netzwerkkabel ziehen oder ähnliches).

UDPClient Anzahl 1..35 = Thread Nummer 2..36

Die Telegramme zu den Clients werden softwareseitig quittiert (da UDP keine Standardmäßige Quittierung hat, ich weiß) und wenn nach einer Zeit X, keine Antwort kommt, wird der Client (=Thread) beendet mit ".Terminate".

Wird das ganze bewusst nur für einen Client (= einen Thread) gemacht mit ".Terminate", passiert an der VCL nichts.
Wird das ganze für 35 gleichzeitig gemacht, dann hängt es.
Soviel habe ich schon rausbekommen

Kas Ob. 21. Mai 2025 11:30

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

Zitat von AJ_Oldendorf (Beitrag 1548793)
Ich versuche es nochmal zu erklären.

Threadübersicht:
UDPServer Anzahl 1 = Thread Nummer 1
UDPClient Anzahl 1..35 = Thread Nummer 2..36
Verarbeitungsthread Anzahl 1..35 = Thread Nummer 37..71
weitere Threads, die für andere Funktionen zuständig sind, allerdings den Verarbeitungsthreads 37..71 auch Nachrichten schicken können.

UDPServer gibt die empfangenen Daten an den UDPClient weiter, via PostThreadMessage
UDPClient gibt Daten nach Prüfung und Validierung und anderen Dingen, an den Verarbeitungsthread weiter, via PostThreadMessage

Verabreitungsthread sieht ungefähr so aus:

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 ;
Wie gesagt, nur ein grober Auszug...

Thank you and well i think we are getting somewhere,
This raise few questions why to mention UDPClient here ? what are their proposes on server side ? if you are responding then use SendTo from the server Binding/Handler to get better idea refer to this example
https://github.com/tinydew4/indy-pro...ServerMain.pas

May be your server doesn't use UDPCLient and this miss understanding on me (translation or something) we get to different problematic approach THE loop
here how to do loop and handle thread messages
https://stackoverflow.com/questions/...ultipleobjects
https://devblogs.microsoft.com/oldne...17-00/?p=36423
Read the question and answers on SO also all the comments there, specially this one
Zitat:

DANGER This is the code that has the bug Raymond wrote about. You need to loop on the peekmessage.

Kas Ob. 21. Mai 2025 11:36

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

Zitat von AJ_Oldendorf (Beitrag 1548795)
Das Verhalten mit dem VCL Hänger scheint genau dann aufzutreten, wenn ich gleichzeitig die Verbindung zu allen 35 UDP Teilnehmern trenne (Netzwerkkabel ziehen oder ähnliches).

UDPClient Anzahl 1..35 = Thread Nummer 2..36

Die Telegramme zu den Clients werden softwareseitig quittiert (da UDP keine Standardmäßige Quittierung hat, ich weiß) und wenn nach einer Zeit X, keine Antwort kommt, wird der Client (=Thread) beendet mit ".Terminate".

Wird das ganze bewusst nur für einen Client (= einen Thread) gemacht mit ".Terminate", passiert an der VCL nichts.
Wird das ganze für 35 gleichzeitig gemacht, dann hängt es.
Soviel habe ich schon rausbekommen

Great, now explain how these are tied to MainThread, are these are the cause or
Verarbeitungsthread Anzahl 1..35 = Thread Nummer 37..71

Either group causing the main thread to block in waiting state, this behaviour red color on CPU usage unless you are not performing IO operations (reading/writing to disk or network in tight loop) then means one thing, high thread contention and main thread is not couping with it jumping from one place to another and have no time to process Messages.

Capture the culprit, try to exit either group before performing this sudden close, see what is wrong and change that timeout at 250ms to something useful like 30seconds (30000ms), you are not expecting messages that much after all.
Can you disconnect all the clients at once form server ? what happen ? etc...

AJ_Oldendorf 21. Mai 2025 12:17

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

Thank you and well i think we are getting somewhere,
This raise few questions why to mention UDPClient here ? what are their proposes on server side ? if you are responding then use SendTo from the server Binding/Handler to get better idea refer to this example
https://github.com/tinydew4/indy-pro...ServerMain.pas

May be your server doesn't use UDPCLient and this miss understanding on me (translation or something) we get to different problematic approach THE loop
here how to do loop and handle thread messages
https://stackoverflow.com/questions/...ultipleobjects
https://devblogs.microsoft.com/oldne...17-00/?p=36423
Read the question and answers on SO also all the comments there, specially this one

Verstehe das Problem nicht. Ich rufe doch PeekMessage in einer While Schleife auf, so wie in dem verlinkten Beitrag.


Zitat:

Great, now explain how these are tied to MainThread, are these are the cause or
Verarbeitungsthread Anzahl 1..35 = Thread Nummer 37..71

Either group causing the main thread to block in waiting state, this behaviour red color on CPU usage unless you are not performing IO operations (reading/writing to disk or network in tight loop) then means one thing, high thread contention and main thread is not couping with it jumping from one place to another and have no time to process Messages.

Capture the culprit, try to exit either group before performing this sudden close, see what is wrong and change that timeout at 250ms to something useful like 30seconds (30000ms), you are not expecting messages that much after all.
Can you disconnect all the clients at once form server ? what happen ? etc...
Es werden nur die UDPClient-Threads beendet mit Terminate. Die Verarbeitungsthread (Anzahl 1..35 = Thread Nummer 37..71) laufen ganz normal weiter aber bekommen keine Daten von den UDPClient-Threads mehr, da diese beendet wurden. Es gibt allerdings noch andere Threads im Programm, welche den Verarbeitungsthreads weiterhin Daten schicken können, deswegen werden diese auch nicht beendet. Doch, die 250ms brauche ich, da ich eine echtzeitnahe Anwendung betreibe und sehr viele Daten mit den Threads austausche. Bitte keine Diskussion über Echtzeitnah, ich weiß, dass dies unter Windows nicht geht. Darum geht es hier auch nicht.

Ich trenne die UDPClients gleichzeitig! und genau dann tritt das Problem auf.
Trenne ich nur EINEN Client, passiert das Problem NICHT.

Kas Ob. 21. Mai 2025 12:56

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

Zitat von AJ_Oldendorf (Beitrag 1548798)
Es werden nur die UDPClient-Threads beendet mit Terminate. Die Verarbeitungsthread (Anzahl 1..35 = Thread Nummer 37..71) laufen ganz normal weiter aber bekommen keine Daten von den UDPClient-Threads mehr, da diese beendet wurden. Es gibt allerdings noch andere Threads im Programm, welche den Verarbeitungsthreads weiterhin Daten schicken können, deswegen werden diese auch nicht beendet. Doch, die 250ms brauche ich, da ich eine echtzeitnahe Anwendung betreibe und sehr viele Daten mit den Threads austausche. Bitte keine Diskussion über Echtzeitnah, ich weiß, dass dies unter Windows nicht geht. Darum geht es hier auch nicht.

Ich trenne die UDPClients gleichzeitig! und genau dann tritt das Problem auf.
Trenne ich nur EINEN Client, passiert das Problem NICHT.

Still missing the point, what are UDPClient-Threads ?

Are they TThread ?
and more important question
Are you using a UDPClient or TIdUDPClient on server part ?

And more importanter then grammar is When you say 250ms is needed ....... WHYYYYYY

What are those thread suppose to do ? Send and/or receive or processing too ? are you piling jobs on threads and for that you need them to wait for 250ms then do another thing ? that is wrong and contradict the point of using threads to begin with.

When you say you have threads to received on the that event then that event is the one coming form dedicated thread allocated by Indy library to handle you recv and send, then use UDP server to send, and in that event just recv/read and utilize its parameter in that even to send when finished, this can be from any other threads (literally from anywhere).

explain in plain text the logic from receiving a packet to send it, do it on paper and you will find the root of these hugs.

Again refer to https://github.com/tinydew4/indy-pro...ServerMain.pas
Delphi-Quellcode:
procedure TUDPMainForm.UDPServerUDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
  DataStringStream: TStringStream;
  s: String;
begin
  DataStringStream := TStringStream.Create('');
  try
    DataStringStream.CopyFrom(AData, AData.Size);
    UDPMemo.Lines.Add('Received "' + DataStringStream.DataString + '" from ' + ABinding.PeerIP + ' on port ' + IntToStr(ABinding.PeerPort));
    s := 'Replied from ' + UDPServer.LocalName + ' to "' + DataStringStream.DataString + '"';
    ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, s[1], Length(s));
  finally
    DataStringStream.Free;
  end;
end;
Do send using "ABinding: TIdSocketHandle" "ABinding.SendTo" from anywhere, in other words no dedicated thread, to duck rubber explain it,
having TIdUDPServer on your application/server will remove the need for threads to receive and send, leaving one group of threads, the processing, you want to dedicate one per client ? ok that is fine, now i want you to question the existence of two group of threads, and explain them.

I am sure you miss understanding one functionality somewhere.

Kas Ob. 21. Mai 2025 13:02

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Receiving from UDP is or can be blocking and can be non blocking, you really don't need to dedicate a thread per identified connection, just recv/read and pass to a thread then write/send from anywhere.

simplify the the groups need and keep only one, also if you like loop like that then wait on call and block on recv then handle then send, loop again, this will even simplify the things further, removing the need to pass data between threads altogether.

Kas Ob. 21. Mai 2025 13:12

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
One more thing to understand, that you might be missing,

UDP is unlike TCP, in case of TCP you can not send without checking the socket is ready to write/send, well you can but it might fail with error and ask you to block or to wait, UDP it is ready always, like always always, just SendTo and call it a day, it might fail or drop the packet but you don't have control about it as there is nothing to do about it, will not explain how to mitigate this here as it is irrelevant your case, 35 clients unless the traffic is saturating you connection it will work like charm.

AJ_Oldendorf 21. Mai 2025 13:25

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Ich versuche auf einige Fragen zu antworten aber das Senden mit UDP hin und her mit softwareseitiger Quittierung funktioniert ja. OHNE VCL Hänger.
Der UDPServer ist ein Thread und empfängt die Daten.
Für jeden UDP Teilnehmer im Netzwerk (=Client), erzeuge ich mir im Server einen eigenen Thread, der dann das Senden an den Client übernimmt (dieser heißt bei mir Client-Thread und ist natürlich ein TThread).
Das Senden macht NICHT der Server-Thread direkt. Der Server gibt dem Client-Thread nur die Hostadresse und Port (vom Empfang) mit.
Im Client-Thread wird ein IdUDPClient erstellt, welcher das Senden übernimmt an Host und Port. Der Client-Thread überwacht auch selber die Quittierung der UDP Telegramme. Daher braucht sich die Server-Komponente NUR um den Empfang kümmern.
Der Datenaustausch mit dem Client-Endgerät, wird durch einen Client-Thread gemacht.
Der Client-Thread überwacht seine MessageQueue mit besagter PeekMessage-Technik und wenn für eine gewisse Zeit, keine Daten mehr eintreffen, wird der Teilnehmer als offline erkannt und der Client-Thread terminiert sich mit ".Terminate"


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:15 Uhr.
Seite 1 von 2  1 2      

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