Delphi-PRAXiS
Seite 2 von 3     12 3      

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)

Kas Ob. 21. Mai 2025 13:42

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

Zitat von AJ_Oldendorf (Beitrag 1548803)
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"

IdUDPClient is a component, did you assign an owner for it ? if yes then this might explain a lot.

IN all cases IdUDPClient is overkill as i explained the from that initial event fired on server side you already have the connection (what called a distinguish identifier for UDP client) along a way to send using SendTo, so introducing IdUDPClient triggering threads that is competing with the server over this connection, is an overhead approach.

Now about that last line, your timeout at 250ms monitoring messages is to switch between
1) check if a message is received then what, either timed out at 250ms which contradict the need for real time or
2) try to read from the client ? or send ?

Still the whole design is not clear.

Just handle the packets in the one recv thread then send from it, even if it is the server triggered event OnRead, because there is something is triggering the main thread to perform some work (a lot of work), and even after all what did you described, this doesn't explain the main thread business.

AJ_Oldendorf 21. Mai 2025 14:14

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
IdUDPClient liegt auf einem Datenmodul welches mit
Delphi-Quellcode:
.Create(Nil);
erzeugt wird.
Also nein, es hat keinen Owner.

Das Senden mit IdUDPClient sieht so aus:
Delphi-Quellcode:
IdUDPClient.SendBuffer(MyDModul.IdUDPClient.Host,
                       MyDModul.IdUDPClient.Port,
                       ByteMsg);
Eine Prüfung genau an dieser Stelle auf "MainThreadID" und "GetCurrentThreadID" sagt auch, KEIN VCL Kontext.

Das Thema mit den 250ms ist in dem Verarbeitungsthread, hat nichts mit dem Client-Thread zu tun! Das Thema sollten wir nicht weiter betrachten.

Richtig, dass Hauptproblem ist nach wie vor die hängende VCL für ~ 7s.
Interessant ist, es sind wirklich immer ~ 7s, bei jedem Test.

Gibt es eine Möglichkeit, dass ich selber herausbekomme, was der VCL Kontext/Thread gerade gemacht? Ich glaube nämlich nicht, dass das UDP Thema damit eine Rolle spielt. Ich kann es nur dadurch erzeugen, da ich damit so viele Threads gleichzeitig beende.

Edelfix 21. Mai 2025 14:28

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Weil ich Indy sehe muss ich an TIdAntiFreeze denken.

Bin mir aber nicht sicher ob das an dieser Stelle hilfreich ist.

himitsu 21. Mai 2025 14:49

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Aber nur wenn man es im Hauptthread verwendet, was hier ja wohl nicht vorkommt.

Kas Ob. 21. Mai 2025 15:13

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

Zitat von AJ_Oldendorf (Beitrag 1548805)
IdUDPClient liegt auf einem Datenmodul welches mit
Delphi-Quellcode:
.Create(Nil);
erzeugt wird.
Also nein, es hat keinen Owner.

Das Senden mit IdUDPClient sieht so aus:
Delphi-Quellcode:
IdUDPClient.SendBuffer(MyDModul.IdUDPClient.Host,
                       MyDModul.IdUDPClient.Port,
                       ByteMsg);
Eine Prüfung genau an dieser Stelle auf "MainThreadID" und "GetCurrentThreadID" sagt auch, KEIN VCL Kontext.

Das Thema mit den 250ms ist in dem Verarbeitungsthread, hat nichts mit dem Client-Thread zu tun! Das Thema sollten wir nicht weiter betrachten.

Richtig, dass Hauptproblem ist nach wie vor die hängende VCL für ~ 7s.
Interessant ist, es sind wirklich immer ~ 7s, bei jedem Test.

Gibt es eine Möglichkeit, dass ich selber herausbekomme, was der VCL Kontext/Thread gerade gemacht? Ich glaube nämlich nicht, dass das UDP Thema damit eine Rolle spielt. Ich kann es nur dadurch erzeugen, da ich damit so viele Threads gleichzeitig beende.

Saying killing so many threads at once can cause this, make my sad.
Here a simple test that will create 50000 threads and exits them, no killing just exit gracefully, creating them in fraction of second and exit them in second(s):
Delphi-Quellcode:
unit Unit10;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TForm10 = class(TForm)
    Timer1: TTimer;
    Label1: TLabel;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    procedure CreateOneThread;
    procedure CreateThreads(Count: Integer);
  public
    { Public declarations }
  end;

var
  Form10: TForm10;

implementation

{$R *.dfm}

var
  CurrentThreadCount: Integer;

const
  CREATE_MANY_THREADS = 50000;
  THREADS_STACK_SIZE = 64 * 1024;
  STACK_SIZE_PARAM_IS_A_RESERVATION = $00010000;

function ThreadFunc(Parameter: Pointer): Integer;
begin
  InterlockedIncrement(CurrentThreadCount);
  Sleep(4000);
  InterlockedDecrement(CurrentThreadCount);
  EndThread(0);
end;

procedure TForm10.FormCreate(Sender: TObject);
begin
  Timer1.Interval := 50;
end;

procedure TForm10.CreateOneThread;
var
  ThreadId: Cardinal;
  ThreadHandle: THandle;
begin
  ThreadHandle := BeginThread(nil, THREADS_STACK_SIZE, Addr(ThreadFunc), 0, STACK_SIZE_PARAM_IS_A_RESERVATION, ThreadId);
  if ThreadHandle <> 0 then
    CloseHandle(ThreadHandle);
end;

procedure TForm10.CreateThreads(Count: Integer);
begin
  while Count > 0 do
  begin
    CreateOneThread;
    Dec(Count);
  end;
end;

procedure TForm10.Button1Click(Sender: TObject);
begin
  if IsDebuggerPresent then
    CreateThreads(10)
  else
    CreateThreads(CREATE_MANY_THREADS);
end;

procedure TForm10.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := IntToStr(CurrentThreadCount);
end;

end.
Build it for 64bit not 32bit, and don't run it in the debugger as it will kill the IDE, try to increase the created and exited threads to 100k, will there be a big difference.

Anyway all Indy components are tied internally to singletons that track their creation and lifetime, using CciticalSection and try to look for singleton that protect from hanging and freezing also for logging...etc..
I am not expert on Indy but you approach even with 35 connection is wrong and cause this.

Away from that there is no solution like put this line and it will work fine.

ps: when running that test of 50k threads watch the red against the green in Process Explorer.

Kas Ob. 21. Mai 2025 15:20

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

Zitat von himitsu (Beitrag 1548808)
Aber nur wenn man es im Hauptthread verwendet, was hier ja wohl nicht vorkommt.

I am pretty much sure it is the main thread problem to begin with, as UDP server is most likely a dropped component on a form or module, this one is creating the socket and listening to the traffic then later another TIdUDPClient form different thread is creating socket and trying to perform recv from the same address, leaving them both competing on shared resource.

The question AJ_Oldendorf did not answer, are there any sort of Synchronize or Thread control functions/method from "TThread." being used ?
is there from TThread beyond Create and Execute being used ? like WaitFor ...

AJ_Oldendorf 22. Mai 2025 05:55

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

Saying killing so many threads at once can cause this, make my sad.
Here a simple test that will create 50000 threads and exits them, no killing just exit gracefully, creating them in fraction of second and exit them in second(s):
Ich habe nicht verstanden, was mir das Beispiel helfen soll.
Es geht bei mir um 35 Threads, nicht um 50000.
Meine Threads sind Objekte vom Typ TThread und werden mit TThread.Create() erstellt.
Warum sind es 35 einzelne Threads mit jeweils einer UDPClient Komponente? Jeder Thread und jeder Teilnehmer, kann zu unterschiedlichen Zeiten unterschiedliche Daten geschickt bekommen. Wird alles in einem Thread abgewickelt wird, müssen sich alle Telegramme durch eine UDPClient-Komponente quälen, so kann jeder Thread an seinen jeweiligen Empfänger (dies ist natürlich auch immer ein anderer, also 35 verschiedene Empfänger) losgelöst arbeiten.

Zitat:

I am pretty much sure it is the main thread problem to begin with, as UDP server is most likely a dropped component on a form or module, this one is creating the socket and listening to the traffic then later another TIdUDPClient form different thread is creating socket and trying to perform recv from the same address, leaving them both competing on shared resource.

The question AJ_Oldendorf did not answer, are there any sort of Synchronize or Thread control functions/method from "TThread." being used ?
is there from TThread beyond Create and Execute being used ? like WaitFor ...
Ich dachte alle Fragen beantwortet zu haben aber hier nochmal zur Klarstellung.
Es wird kein Synchronize im Programm verwendet. Es wird kein WaitFor... im Programm verwendet. Class functions/method von "TThread." (wie TThread.Queue) wird nicht verwendet. Ich habe reine Variablen/Objekte vom Typ TThread und die werden mit .Create erstellt und nur über den Variablennamen darauf zugegriffen.

Ich möchte nochmal auf das Hauptproblem zurück kommen.
VCL Hänger.
Wie kann ich in meinem Programm selbstständig feststellen, wer die VCL blockieren könnte bzw was der VCL Thread aktuell macht.
Vielleicht wird ja auch aus irgendeinen unbekannten Grund, eine rechenintensive Funktion durch den VCL Thread bearbeitet, was natürlich auch den Hänger erklären würde

shebang 22. Mai 2025 08:10

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

Zitat von AJ_Oldendorf (Beitrag 1548834)
Wie kann ich in meinem Programm selbstständig feststellen, wer die VCL blockieren könnte bzw was der VCL Thread aktuell macht.

Du lässt das Programm im Debugger laufen und während des VCL Hängers pausiert du den Debugger. Aus der Threadliste suchst du dir dann den VCL Thread heraus und guckst dir im Stacktrace an, in welcher Funktion er steckt. Je nachdem was er gerade macht, musst du das ein paar mal wiederholen.

Kas Ob. 22. Mai 2025 08:55

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
That example shows how threads are magnificent beasts on Windows, 50k are feather light in creating and exiting, (notice it might be translation problem as i read killing threads), yet it takes only 4 on my 4-core CPU to destroy my whole OS experience, the example is to show you you are after the wrong reason, creating and exiting threads is fast.

Zitat:

Zitat von AJ_Oldendorf (Beitrag 1548834)
Ich möchte nochmal auf das Hauptproblem zurück kommen.
VCL Hänger.
Wie kann ich in meinem Programm selbstständig feststellen, wer die VCL blockieren könnte bzw was der VCL Thread aktuell macht.
Vielleicht wird ja auch aus irgendeinen unbekannten Grund, eine rechenintensive Funktion durch den VCL Thread bearbeitet, was natürlich auch den Hänger erklären würde

Same as my first post in this thread, use a profiler and it will pin point the long VCL operation.

See you insist on creating one UDPClient per connection on a server, that is wrong, you said you are not assigning and owner, yet in the same phrase they are on DataModule
Zitat:

IdUDPClient liegt auf einem Datenmodul welches mit .Create(Nil); erzeugt wird.
Also nein, es hat keinen Owner.
It could be something missed in translation.

My final words here is, there is no unknown reason for this, there is broken logic and false assumptions, so no, not Windows faults, not network adapter faults, and not Delphi RTL/VCL fault.
Remove the UDPClient creation, make sure you are not creating TDataModule with punch of components on it per client, simplify the logic into one thread per one client doing it all and this freeze will disappear.

AJ_Oldendorf 22. Mai 2025 09:33

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

Du lässt das Programm im Debugger laufen und während des VCL Hängers pausiert du den Debugger. Aus der Threadliste suchst du dir dann den VCL Thread heraus und guckst dir im Stacktrace an, in welcher Funktion er steckt. Je nachdem was er gerade macht, musst du das ein paar mal wiederholen.
Danke, dass werde ich versuchen.

Zitat:

Same as my first post in this thread, use a profiler and it will pin point the long VCL operation.
Ich wollte es gerne nach Möglichkeit gerne selber erkennen und keine Fremdsoftware dafür installieren.

Zitat:

See you insist on creating one UDPClient per connection on a server, that is wrong, you said you are not assigning and owner, yet in the same phrase they are on DataModule
Ich habe es auch ohne Datenmodul versucht und die UDPClient Komponente als Variable im Threadobjekt deklariert. Das hat kein Unterschied ausgemacht. Liegt also nicht daran.

Ich sage auch nicht, dass Beenden von Threads generell lange dauert. Das wäre sicherlich schon jemanden vor mir aufgefallen, wenn es denn so wäre :-D Ich sage nur, wie ich es erzeugen kann, woran es tatsächlich liegt, suche ich ja noch

AJ_Oldendorf 22. Mai 2025 10:19

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Du lässt das Programm im Debugger laufen und während des VCL Hängers pausiert du den Debugger. Aus der Threadliste suchst du dir dann den VCL Thread heraus und guckst dir im Stacktrace an, in welcher Funktion er steckt. Je nachdem was er gerade macht, musst du das ein paar mal wiederholen.
Das habe ich versucht. In dem Moment wo ich auf Pause klicke in der IDE, minimiert sich die IDE. Meine Anwendung läuft bis dahin wieder (sind ja "nur" 7s der Hänger). Klicke ich auf die minimierte IDE in der Taskleiste, geht diese wieder auf und es steht nur eine Fehlermeldung da, dass der Debugger bereits gestoppt wurde. Pausiert wurde aber nicht und die Anwendung von mir läuft wieder ganz normal ohne Hänger.
Dazu eine Idee?

Mavarik 22. Mai 2025 11:40

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

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

Zitat:

Zitat von AJ_Oldendorf (Beitrag 1548734)
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 :coder:

AJ_Oldendorf 22. Mai 2025 11:52

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

Uwe Raabe 22. Mai 2025 12:01

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Ich kann es aus dem Code zwar nicht direkt ersehen, aber das MsgWaitXXX wartet vermutlich auf den/die Thread(s), die im weiteren Verlauf mit PostThreadMessage beliefert werden sollen. Das wird in der MS-Doku auch genauso beschrieben.

Aber trotz aller oft sicher auch berechtigter Kritik: Das Problem ist offenbar nicht in dem gezeigten Code zu finden. Das Kappen einer größeren Menge von Verbindungen und das daraus folgende Terminieren der Threads ist nicht die Ursache für das Hängen der VCL. Vielmehr löst es diese nur aus. Es geht also darum, die Ursache für den Hänger zu finden. Den Auslöser kennen wir nun ja schon.

AJ_Oldendorf 22. Mai 2025 12:07

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

Ich kann es aus dem Code zwar nicht direkt ersehen, aber das MsgWaitXXX wartet vermutlich auf den/die Thread(s), die im weiteren Verlauf mit PostThreadMessage beliefert werden sollen. Das wird in der MS-Doku auch genauso beschrieben.
Das wartet doch aber nur auf NEUE Messages für genau diesen Thread.
Warum sollte ein PostThreadMessage von jemand anderen (von außen) an genau diesen Thread, zu einem warten führen? Das ist mir nicht ganz klar.

Zitat:

Aber trotz aller oft sicher auch berechtigter Kritik: Das Problem ist offenbar nicht in dem gezeigten Code zu finden. Das Kappen einer größeren Menge von Verbindungen und das daraus folgende Terminieren der Threads ist nicht die Ursache für das Hängen der VCL. Vielmehr löst es diese nur aus. Es geht also darum, die Ursache für den Hänger zu finden. Den Auslöser kennen wir nun ja schon.
Danke Uwe, da stimme ich dir absolut zu. Die Frage ist immernoch, wie bekomme ich raus, was die VCL genau in dem Moment macht? Das pausieren des Debuggers geht ja leider nicht

Uwe Raabe 22. Mai 2025 13:17

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

Zitat von AJ_Oldendorf (Beitrag 1548851)
Warum sollte ein PostThreadMessage von jemand anderen (von außen) an genau diesen Thread, zu einem warten führen? Das ist mir nicht ganz klar.

Nicht zu einem Warten, aber zu einem Fehler (siehe https://learn.microsoft.com/en-us/wi...ssagea#remarks - das Bold ist von mir) :
Zitat:

The thread to which the message is posted must have created a message queue, or else the call to PostThreadMessage fails. Use the following method to handle this situation.
  • Create an event object, then create the thread.
  • Use the WaitForSingleObject function to wait for the event to be set to the signaled state before calling PostThreadMessage.
  • In the thread to which the message will be posted, call PeekMessage as shown here to force the system to create the message queue.
    Delphi-Quellcode:
    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)
  • Set the event, to indicate that the thread is ready to receive posted messages.
The thread to which the message is posted retrieves the message by calling the GetMessage or PeekMessage function. The hwnd member of the returned MSG structure is NULL.
---
Zitat:

Zitat von AJ_Oldendorf (Beitrag 1548851)
Die Frage ist immernoch, wie bekomme ich raus, was die VCL genau in dem Moment macht? Das pausieren des Debuggers geht ja leider nicht

Das ist in der Tat nicht ganz so einfach. Das Hängen der VCL kann ziemlich viele Ursachen haben. Das kann z.B. auch das Schreiben einer Datei im MainThread sein, die vom Virenwächter oder dem Netzwerk ausgebremst wird. Du könntest ja mal zum Test das gesamte Logging ausblenden. Wenn es dann immer noch zu einem Hänger kommt, wird es daran vermutlich erstmal nicht liegen.

AJ_Oldendorf 22. Mai 2025 13:43

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

Nicht zu einem Warten, aber zu einem Fehler (siehe https://learn.microsoft.com/en-us/wi...ssagea#remarks - das Bold ist von mir) :
Ok, ich hatte dich falsch verstanden. Das PostThreadMessage erzeugt aber keinen Fehler, habe überall ein Else-Zweig und ein Breakpoint da drauf. Kommt nicht da rein.

Zitat:

Das ist in der Tat nicht ganz so einfach. Das Hängen der VCL kann ziemlich viele Ursachen haben. Das kann z.B. auch das Schreiben einer Datei im MainThread sein, die vom Virenwächter oder dem Netzwerk ausgebremst wird. Du könntest ja mal zum Test das gesamte Logging ausblenden. Wenn es dann immer noch zu einem Hänger kommt, wird es daran vermutlich erstmal nicht liegen.
Das werde ich mal versuchen.

Würde gerne nochmal darauf zurück kommen:
Zitat:

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.
Wenn jemand da etwas hat mit Daten über eine Liste und gleichzeitig Messagebehandlung/Event, dann würde ich das gerne mal versuchen

AJ_Oldendorf 22. Mai 2025 13:55

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

Das werde ich mal versuchen.
Logging deaktivieren:
Hat keinen Effekt auf die VCL. Hätte mich auch gewundert, da alles was mit Logging zu tun hat, an einen zentralen Log-Thread per PostThreadMessage geschickt wird und der liest entsprechend auch seine Queue aus und schreibt dann in die Datei.

Muss also noch was anderes sein...

shebang 22. Mai 2025 14:39

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

Zitat von AJ_Oldendorf (Beitrag 1548846)
In dem Moment wo ich auf Pause klicke in der IDE, minimiert sich die IDE. Meine Anwendung läuft bis dahin wieder (sind ja "nur" 7s der Hänger). Klicke ich auf die minimierte IDE in der Taskleiste, geht diese wieder auf und es steht nur eine Fehlermeldung da, dass der Debugger bereits gestoppt wurde. Pausiert wurde aber nicht und die Anwendung von mir läuft wieder ganz normal ohne Hänger.
Dazu eine Idee?

Funktioniert das Debugging denn in anderen Projekten korrekt?

Delphi.Narium 22. Mai 2025 14:49

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

Zitat von AJ_Oldendorf (Beitrag 1548798)
Ich trenne die UDPClients gleichzeitig! und genau dann tritt das Problem auf.
Trenne ich nur EINEN Client, passiert das Problem NICHT.

Tritt das Problem nicht auf oder dauert es nur ein fünfundreißigstel so lang (und fällt deshalb nicht auf)?

Zeigt doch einfach mal den Quellcode, mit dem die UDPClients gleichzeitig getrennt werden. Hier scheint ja das Problem zu liegen. Eventuell macht der VCL-Thread in der Zeit ja garnichts, sondern wird von Windows erst wieder an die Arbeit gelassen, wenn alle UDPClients beendet sind?

Mögliche blockierende Freigabeoperationen(?):

Socket-Cleanup bei UDP-Clients erfolgt synchron im Hauptthread?

Massenhafte Freigabe (35 Clients) blockiert die Nachrichtenverarbeitung?

QuickAndDirty 22. Mai 2025 16:33

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Läuft für jeden UDPClient eine SVCHOST.exe?

AJ_Oldendorf 23. Mai 2025 05:08

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

Funktioniert das Debugging denn in anderen Projekten korrekt?
Es funktioniert auch in dem selben Projekt, wenn die VCL nicht hängt. Dann wird ganz normal die CPU Ansicht geöffnet. Es geht nur nicht, wenn die VCL hängt.

Zitat:

Tritt das Problem nicht auf oder dauert es nur ein fünfundreißigstel so lang (und fällt deshalb nicht auf)?

Zeigt doch einfach mal den Quellcode, mit dem die UDPClients gleichzeitig getrennt werden. Hier scheint ja das Problem zu liegen. Eventuell macht der VCL-Thread in der Zeit ja garnichts, sondern wird von Windows erst wieder an die Arbeit gelassen, wenn alle UDPClients beendet sind?

Mögliche blockierende Freigabeoperationen(?):

Socket-Cleanup bei UDP-Clients erfolgt synchron im Hauptthread?

Massenhafte Freigabe (35 Clients) blockiert die Nachrichtenverarbeitung?
Es wird einfach in einer Schleife, ein PostThreadMessage mit einer speziellen Nachrichtenkennung an die Threads geschickt, welche ja über das bekannte Konstrukt (PeekMessage) die Nachrichtenqueue ausliest und dort ein Terminate ausführt. Im Destroy des Threads, wird der
Delphi-Quellcode:
UDPClient.Active := False
zugewiesen und die Komponente freigegeben. Das wars.

Zitat:

Läuft für jeden UDPClient eine SVCHOST.exe?
Nein, sollte es denn?

Eine Sache habe ich mittlerweile rausgefunden.
Es liegt NICHT an UDP!
Ich habe im System noch viel mehr Threads und ich habe mal ein Test gemacht, andere Threads, die völlig andere Aufgaben haben, zu beenden.
Hier tritt das gleiche Problem auf. Es ist also ein grundlegendes Problem. Ich werde weiter suchen, woran das liegen könnte.

Daher nochmal meine Frage, ihr sprecht von Threadsicheren Listen und keine MessageQueue mit PeekMessage abgrasen und Events triggern. Habt ihr mal ein funktionierendes Beispiel, wie man ein Thread über so eine threadsichere Liste "Nachrichten" zukommen lassen kann und parallel dazu noch mit Events auf bestimmte Dinge triggern kann? Dann würde ich das auch gerne mal umbauen und versuchen

Stevie 23. Mai 2025 06:57

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

Zitat von AJ_Oldendorf (Beitrag 1548841)
Zitat:

Same as my first post in this thread, use a profiler and it will pin point the long VCL operation.
Ich wollte es gerne nach Möglichkeit gerne selber erkennen und keine Fremdsoftware dafür installieren.

Ist das noch selber, wenn man seit 4 Tagen im Forum darüber analysiert? :gruebel: Mit einem Profiler hättest du die Stelle vermutlich schon Dienstag Abend gefunden.
Ein Profiler wird dir genau zeigen können, was in dem besagten Zeitraum im Code passiert und wo er gerade steht - das kann dir keiner hier sagen, solang es aus verständlichen Gründen nur Codeschnipsel gibt.

QuickAndDirty 23. Mai 2025 10:20

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

Zitat von AJ_Oldendorf (Beitrag 1548867)
Daher nochmal meine Frage, ihr sprecht von Threadsicheren Listen und keine MessageQueue mit PeekMessage abgrasen und Events triggern. Habt ihr mal ein funktionierendes Beispiel, wie man ein Thread über so eine threadsichere Liste "Nachrichten" zukommen lassen kann und parallel dazu noch mit Events auf bestimmte Dinge triggern kann? Dann würde ich das auch gerne mal umbauen und versuchen

Thread sicher ist ja einfach mittels Synchronisationsobjekten herstellbar...das Problem ist das man inder Regel dabei die Nebenläufigkeit, vorrübergehend reduziert oder ganz aushebelt oder einen Deadlock erzeugt.

Es gibt allerdings lockfreie Queues mit denen das geht! Mann kann die als "Channel" benutzen. Die sind dann zwar Lockfrei jedoch erzeugen die für sich ne menge Aufwand...jedoch diesen aben vollständig ohne die Nebenläufigkeit zu behindern.
Die OmniThreadLibrary bietet sowas. Aber ich habe die nie benutzt...und ich habe den code nicht gut genug verstanden um die Lockfree-Collections auszubauen und zu verweden.

Falls es die architektonish darum geht einige lang laufende Threads zu haben und diese immer weieder mal mit einer Aufgabe zu versorgen. Dieses problem verspricht die Darkthreading-Library zu lösen....die hat keinen Lockfreien Ansatz sondern nennt es "Light-locking".


Ich warte noch auf eine mit "Fearless-Concurency" werbende Multithreading library. Die werde ich dann direkt übernehmen.

AJ_Oldendorf 23. Mai 2025 10:44

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

Ist das noch selber, wenn man seit 4 Tagen im Forum darüber analysiert? Mit einem Profiler hättest du die Stelle vermutlich schon Dienstag Abend gefunden.
Ein Profiler wird dir genau zeigen können, was in dem besagten Zeitraum im Code passiert und wo er gerade steht - das kann dir keiner hier sagen, solang es aus verständlichen Gründen nur Codeschnipsel gibt.
Nexus_Quality_Suite installiert aber leider nicht wirklich zum Laufen bekommen mit meiner Anwendung und einer Überwachung.
Wieder deinstalliert.
Eurekalog installiert, im Projekt hinzugefügt, Hang Detection angeklickt und auf 1s gestellt. Anwendung gestartet, Fehlverhalten erzeugt (OnIdle Event wurde auch entsprechend 5s nicht aufgerufen und VCL hängt), Was müsste jetzt passieren? Eurekalog zeigt kein Fenster (hätte ich evtl. erwartet). Ich fahre die Anwendung runter. Auch keine LogDatei mit irgendwelchen Infos zu dem Hänger gefunden. Gibts noch ein Trick?

Genau aus dem Grund, wollte ich es selber finden, da auch die Profiler keine Wunderlösung sind und entsprechend konfiguriert oder ähnliches gemacht werden muss.
Ich sage nicht, dass die nicht funktionieren. Ich sage nur, es ist kein installieren und Fehler wurde gefunden im Programm.

Hier vielleicht jemand ein Tipp dazu?

Zitat:

Thread sicher ist ja einfach mittels Synchronisationsobjekten herstellbar...das Problem ist das man inder Regel dabei die Nebenläufigkeit, vorrübergehend reduziert oder ganz aushebelt oder einen Deadlock erzeugt.

Es gibt allerdings lockfreie Queues mit denen das geht! Mann kann die als "Channel" benutzen. Die sind dann zwar Lockfrei jedoch erzeugen die für sich ne menge Aufwand...jedoch diesen aben vollständig ohne die Nebenläufigkeit zu behindern.
Die OmniThreadLibrary bietet sowas. Aber ich habe die nie benutzt...und ich habe den code nicht gut genug verstanden um die Lockfree-Collections auszubauen und zu verweden.

Falls es die architektonish darum geht einige lang laufende Threads zu haben und diese immer weieder mal mit einer Aufgabe zu versorgen. Dieses problem verspricht die Darkthreading-Library zu lösen....die hat keinen Lockfreien Ansatz sondern nennt es "Light-locking".


Ich warte noch auf eine mit "Fearless-Concurency" werbende Multithreading library. Die werde ich dann direkt übernehmen
Ich gucke mir das mal an aber ich habe die Beiträge mit den vielen Denkanstößen so verstanden, dass es generell threadsichere Queues/Listen gibt, die man nutzen kann um mit Threads zu arbeiten? Gleichzeitig wird immer auf Events verwiesen um die Threads anzutriggern.
Aber irgendwie scheint es keine Beispiele dazu zu geben, wo man sich das konkret angucken und nutzen könnte. Zum aktuellen Zeitpunkt helfen die Denkanstöße leider nicht wirklich

Edelfix 23. Mai 2025 10:49

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Meine letzter Stand ist das wenn man es ganz genau nimmt keine block free Queue existiert.

Queue ist sie nicht wirklich "lock-free", sondern eher ein Thread-sicheres Kommunikationsmittel mit minimaler Sperrung, besonders optimiert für mehr Leser als Schreiber oder umgekehrt.

Der Grund ist das immer TMonitor verwendet wird. Und TMonitor arbeitet mit lock.

Ausnahme: Lock-Free Ring-Buffer. Habe aber keine Erfahrung damit.

Übersicht:
Option / Thread-sicher / Echt lock-free / Einfach zu nutzen / Performance
TThreadedQueue<T> / ✅ / ❌ / ✅ / Hoch
Deltics LockFreeQueue / ✅ / ✅ / ✅ / Sehr hoch
Eigene Ring-Buffer / ✅ / ✅ / ❌ (komplex) Extrem hoch
Windows SLIST APIs / ✅ / ✅ / ❌ (sehr komplex) Extrem hoch

Edelfix 23. Mai 2025 11:01

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Eine Idee wäre: Ein array[0..N] of Queue, bei dem jeder Thread genau eine eigene Queue hat.

Delphi-Quellcode:
ThreadQueues: array[0..MaxThreads - 1] of TThreadedQueue<string>;

constructor TWorkerThread.Create(AQueueIndex: Integer);
begin
  inherited Create(False);
  FQueueIndex := AQueueIndex;
end;

procedure TWorkerThread.Execute;
var
  Msg: string;
begin
  while not Terminated do
  begin
    Msg := Format('Thread %d arbeitet...', [FQueueIndex]);
    ThreadQueues[FQueueIndex].Enqueue(Msg);
    Sleep(Random(100));
  end;
end;
Keine Ahnung ob das geht. Aber so würde immer nur ein Thread schreiben und nur der Hauptthread lesen.

AJ_Oldendorf 23. Mai 2025 11:33

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Meine Idee dazu wäre ja, für jeden Thread eine eigene Liste anzulegen ähnlich dem Konstrukt was ich mal von Sebastian erhalten habe:

Delphi-Quellcode:
  TDataQueue = class
  private
    FQueue: TQueue<TDataRec>;
    FLock: TCriticalSection;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Enqueue(const Data: TDataRec);
    function Dequeue: TDataRec;
  end;

constructor TDataQueue.Create;
begin
  FQueue := TQueue<TDataRec>.Create;
  FLock := TCriticalSection.Create;
end;

destructor TDataQueue.Destroy;
begin
  FQueue.Free;
  FLock.Free;
  inherited;
end;

procedure TDataQueue.Enqueue(const Data: TDataRec);
begin
  FLock.Acquire;
  try
    FQueue.Enqueue(Data);
  finally
    FLock.Release;
  end;
end;

function TDataQueue.Dequeue: TDataRec;
begin
  FLock.Acquire;
  try
    if FQueue.Count > 0 then
      Result := FQueue.Dequeue
    else
    begin
      Result.Clear;
    end;
  finally
    FLock.Release;
  end;
end;


TMyThread = class(TThread)
private
  FDataQueue: TDataQueue;
protected
  procedure Execute; override;
public
  constructor Create(ADataQueue: TDataQueue);
end;

constructor TMyThread.Create(ADataQueue: TDataQueue);
begin
  FDataQueue := ADataQueue;

  Inherited Create(False);
end;

procedure TMyThread.Execute;
var
  RecData : TDataRec;
begin
  while not Terminated do
  begin
    if Terminated then
      Exit;

    if Assigned(FDataQueue) then
    begin
      if FDataQueue.Count > 0 then
      begin
        RecData := FDataQueue.Dequeue;
        //Hier etwas mit den Daten/der Nachricht machen
      end
      else
      begin
        Sleep(1);
      end;
    end;
  end;
end;
Das müsste soweit mit der Abarbeitung einer Liste mit Nachrichten ja gehen oder habe ich was übersehen?

Irgendein anderer Thread trägt dann in die Liste die Daten so ein:

Delphi-Quellcode:
FDataQueue.Enqueue(Daten);

Wie würde man aber das Konstrukt oben noch umbauen, damit es auch mit Events arbeitet.
So pollt der Thread ja die ganze Zeit die Liste ab, deswegen auch das Sleep, damit die CPU Auslastung runter geht.
Jetzt möchte ich dem Thread aber auch noch bestimmte Events schicken z.B. aus meiner Ursprungsvariante das PostThreadMessage zum terminieren des Threads

AJ_Oldendorf 23. Mai 2025 11:34

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Übrigens nochmal zu meinem Hauptproblem mit dem VCL Hänger.

Ich habe festgestellt, dass der Hänger nur passiert, wenn die Anwendung als 64bit compiliert wurde.
Unter 32bit passiert es nicht.

QuickAndDirty 23. Mai 2025 11:56

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

Zitat von AJ_Oldendorf (Beitrag 1548877)
Ich gucke mir das mal an aber ich habe die Beiträge mit den vielen Denkanstößen so verstanden, dass es generell threadsichere Queues/Listen gibt, die man nutzen kann um mit Threads zu arbeiten? Gleichzeitig wird immer auf Events verwiesen um die Threads anzutriggern.
Aber irgendwie scheint es keine Beispiele dazu zu geben, wo man sich das konkret angucken und nutzen könnte. Zum aktuellen Zeitpunkt helfen die Denkanstöße leider nicht wirklich

Oh.
Wenn dir der standard reicht.

Alle Objekte von Delphi haben einen monitor. Damit kannst du den zugriff auf dieses Objekt threadsicher machen.
Das heist DU blockiert alle zugriffe auf das Objekt bis auf einen und alle threads warten in einer warte schlange und stehen so lange bis sie drann sind.

TMonitor leistet das selbe wie TCriticalsection...nur das der Monitor halt schon teil des Objekts ist, während TCriticalsection von dir in alle möglichen kontexte gesetzt werden kann.

Delphi-Quellcode:
TMonitor.enter(MessageQueue);
try
  MessageQueue.add('einen text');
finally
  TMonitor.exit(MessageQueue);
end;
Das macht den Zugriff auf MessageQueue wenn konsequent über all so angewendet threadsicher, durch blockieren der nebenläufigkeit im Tmonitor.enter!


Threads können pausiert und aktiviert werden über TEvent...es ist ein signal
Delphi-Quellcode:
var ZweiThreadsKennenMich := TEvent.create;

ZweiThreadsKennenMich.ResetEvent; //Event Nicht triggered

TTask.run(
  Procedure
  Begin
    if ZweiThreadsKennenMich.Waitfor(60000) = wrSignaled then
      PlaySound
    else
    begin
      //zu lange gewartet
      ZweiThreadsKennenMich.ResetEvent;
    end  
  end
);

ZweiThreadsKennenMich.SetEvent; // triggered das event und Sound wird abgespielt.

QuickAndDirty 23. Mai 2025 12:00

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

Zitat von AJ_Oldendorf (Beitrag 1548882)
Übrigens nochmal zu meinem Hauptproblem mit dem VCL Hänger.

Ich habe festgestellt, dass der Hänger nur passiert, wenn die Anwendung als 64bit compiliert wurde.
Unter 32bit passiert es nicht.

Kann es sein das LLVM Threads auf eine seltsameweise dealociert?

AJ_Oldendorf 23. Mai 2025 12:14

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

Wenn dir der standard reicht.

Alle Objekte von Delphi haben einen monitor. Damit kannst du den zugriff auf dieses Objekt threadsicher machen.
Das heist DU blockiert alle zugriffe auf das Objekt bis auf einen und alle threads warten in einer warte schlange und stehen so lange bis sie drann sind.

TMonitor leistet das selbe wie TCriticalsection...nur das der Monitor halt schon teil des Objekts ist, während TCriticalsection von dir in alle möglichen kontexte gesetzt werden kann.
Meine Liste ist doch beim Enqueue und Dequeue bereits durch ein Lock geschützt. Da brauche ich TMonitor doch nicht mehr oder?

Wie würde dein Beispiel denn aussehen, wenn du es mit 2 verschiedenen Events ausstattest und das in meinen Thread implementierst, der ja bereits die MessageQueue pollt?

Zitat:

Kann es sein das LLVM Threads auf eine seltsameweise dealociert?
Gute Frage, wollte die Info nur erstmal weitergeben

Stevie 23. Mai 2025 12:17

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

Zitat von QuickAndDirty (Beitrag 1548884)
Kann es sein das LLVM Threads auf eine seltsameweise dealociert?

Was hat LLVM mit ner 64bit VCL Anwendung zu tun?

Zitat:

Zitat von AJ_Oldendorf (Beitrag 1548882)
Übrigens nochmal zu meinem Hauptproblem mit dem VCL Hänger.

Ich habe festgestellt, dass der Hänger nur passiert, wenn die Anwendung als 64bit compiliert wurde.
Unter 32bit passiert es nicht.

Dann würde ich mal gucken, ob nicht irgendwo was nicht richtig 64bit kompatibel ist in deinem Code.

Zum Profiling:

- Anwendung mit mapfiles detailed bauen (am besten auch debug dcus Haken setzen)
- SamplingProfiler (pfff, die Seite sagt immer noch kompatibel bis XE4 32bit, Blödsinn, 64bit und neuste Versionen gehen - ich werd Eric nochmal darauf aufmerksam machen) nehmen, in den Sampling Options "Start sampling on command only" wählen und Samples Gathering Mode auf "Monte Carlo Samples" stellen. Im code vor der entsprechenden Stelle ein
Delphi-Quellcode:
OutputDebugString('SAMPLING ON')
, was dem Profiler mitteilt, dass es ab hier losgehen soll, danach ggf dasselbe mit OFF. Dann ein Blick ins Ergebnis, was da auftaucht. Gut möglich, dass das nicht zielführend ist. Dann kann man noch mit VTune schießen.

Oder man geht ganz pragmatisch über den Sysinternal Process Explorer her und schaut sich den Callstack zum Zeitpunkt des Freezes an - nicht selten der Fall, dass ich bei sowas direkt ein WaitForSingleObject oder ähnliche Kandidaten finde.

AJ_Oldendorf 23. Mai 2025 12:40

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

Dann würde ich mal gucken, ob nicht irgendwo was nicht richtig 64bit kompatibel ist in deinem Code.

Zum Profiling:

- Anwendung mit mapfiles detailed bauen (am besten auch debug dcus Haken setzen)
- SamplingProfiler (pfff, die Seite sagt immer noch kompatibel bis XE4 32bit, Blödsinn, 64bit und neuste Versionen gehen - ich werd Eric nochmal darauf aufmerksam machen) nehmen, in den Sampling Options "Start sampling on command only" wählen und Samples Gathering Mode auf "Monte Carlo Samples" stellen. Im code vor der entsprechenden Stelle ein OutputDebugString('SAMPLING ON') , was dem Profiler mitteilt, dass es ab hier losgehen soll, danach ggf dasselbe mit OFF. Dann ein Blick ins Ergebnis, was da auftaucht. Gut möglich, dass das nicht zielführend ist. Dann kann man noch mit VTune schießen.
Danke, werde ich testen. Du meinst ich muss
Delphi-Quellcode:
OutputDebugString('SAMPLING ON')
aufrufen, zu dem Zeitpunkt vor dem Hänger und
Delphi-Quellcode:
OutputDebugString('SAMPLING OFF')
wenn der Hänger vorbei ist, richtig?

Zitat:

Oder man geht ganz pragmatisch über den Sysinternal Process Explorer her und schaut sich den Callstack zum Zeitpunkt des Freezes an - nicht selten der Fall, dass ich bei sowas direkt ein WaitForSingleObject oder ähnliche Kandidaten finde.
Da der Freeze ja nur "kurz" ist, habe ich da überhaupt eine Chance mit dem Process Explorer? Ich habe damit noch nicht viel gearbeitet, muss mal gucken wo man da den Callstack sieht und ob man da schnell hinkommt zum Zeitpunkt des Hängers

Stevie 23. Mai 2025 12:53

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

Zitat von AJ_Oldendorf (Beitrag 1548887)
Danke, werde ich testen. Du meinst ich muss
Delphi-Quellcode:
OutputDebugString('SAMPLING ON')
aufrufen, zu dem Zeitpunkt vor dem Hänger und
Delphi-Quellcode:
OutputDebugString('SAMPLING OFF')
wenn der Hänger vorbei ist, richtig?

Richtig - ggf kannst du auf das off verzichten und einfach direkt auf den Stop Knopf im Profiler klicken wenn der Freeze vorbei is - es geht halt darum, dass man nur das recorded was innerhalb des problematischen Zeitraums passiert. SamplingProfiler listet hier im Gegensatz zu "großen" Profilern wie VTune oder Superluminal nicht die Samples in einer Timeline auf, in der man im Nachhinein schauen kann, was im Zeitraum X so los war.

Zitat:

Zitat von AJ_Oldendorf (Beitrag 1548887)
Da der Freeze ja nur "kurz" ist, habe ich da überhaupt eine Chance mit dem Process Explorer? Ich habe damit noch nicht viel gearbeitet, muss mal gucken wo man da den Callstack sieht und ob man da schnell hinkommt zum Zeitpunkt des Hängers.

Bei kurzen Freezes ist das eher witzlos, da hast du recht.

QuickAndDirty 23. Mai 2025 12:57

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

Zitat von Stevie (Beitrag 1548886)
Was hat LLVM mit ner 64bit VCL Anwendung zu tun?

War es nicht so dass der Hersteller von Delphi den 64Bit compiler nicht nochmal geschrieben hat sondern für alle versionen die nicht Win32 sind konsequent LLVM als compiler ziel benutzt? Ich weiß nicht wie sehr LOW LEVEL LLVM wirlich ist oder ob vielleicht threads ein paar high level ansätze haben.

habe mal nachgesehen...
tatsächlich
sind nur diese LLVM basiert
DCCIOSARM
DCCIOSARM64
DCCAARM
DCCAARM64
DCCLINUX64
DCCOSX64
also ist Windows64 einfach nur ein sau langsamer compiler, ohne guten grund.
Das hat mich wohl in die irre geführt.

AJ_Oldendorf 26. Mai 2025 06:01

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Liste der Anhänge anzeigen (Anzahl: 2)
@Stevie:
Moin, habe das mal untersucht und nachdem ich auf den Stop Button im Profiler geklickt hatte, kam nach ein paar Sekunden die Anzeige, dass das Programm keine Rückmeldung mehr hat. Im Taskmanager waren 0% CPU Auslastung unf 12MB Speicher belegt. Meine Anwendung lief währenddessen noch weiter. Diese habe ich dann manuell beendet und dann kam der Profiler auch wieder "zurück". 94% Local und Global Ratio mit 4828 Samples ist die win32u.dll mit dem Aufruf NtUserMsgWaitForMultipleObjectsEx.
Ich denke mal, dass heißt, dort steht er am längsten drinne oder?
Das ist eigentlich auch klar, da dieser Aufruf von meinen Threads überall so gemacht wird (mit der MessageQueue) und dann anschließend mit dem PeekMessage.
Im Profiler die ersten Funktionen, die direkt mit meinem Quelltext zu tun haben, sind bei einem Ratio von 0.04% und <4 Samples.

So richtig sagt mir das jetzt erstmal noch nichts

Edit: Ich habe zu dem Thema Thread, Queue und Events ein separaten Beitrag aufgemacht, da es in diesem Beitrag eigentlich um die Analyse des VCL Hängers gehen soll

AJ_Oldendorf 26. Mai 2025 06:58

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
So, neue Erkenntnisse:

Aufgrund des Profilers von Stevie, bin ich darauf aufmerksam geworden, dass ich den Hänger 2x nicht nachstellen konnte.
Warum?
Weil die Exe aus dem Profiler gestartet wurde und nicht aus der IDE.

Nochmal den Test ohne Profiler gemacht und es ist tatsächlich so.

Starte ich die Anwendung aus der Delphi IDE, kann ich den Fehler jedes Mal reproduzieren.
Starte ich die Anwendung OHNE die Delphi IDE, ist es nicht mehr reproduzierbar.

Mehrmals mit beiden Konstellationen versucht und immer das gleiche Ergebnis.
Also hängt sich der Debugger da irgendwo rein und erzeugt den Hänger in irgendeiner Form...
Na toll, muss man erstmal drauf kommen

TomyN 26. Mai 2025 07:46

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
 
Hast Du schon mal den Application Verifier probiert?

jaenicke 26. Mai 2025 07:47

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

Zitat von AJ_Oldendorf (Beitrag 1548947)
Also hängt sich der Debugger da irgendwo rein und erzeugt den Hänger in irgendeiner Form...

Der Unterschied liegt insbesondere bei Multithreadanwendungen im Timing beim Threadscheduling. Das Zusammenspiel der Threads ändert sich dadurch.

Das kann auch umgekehrt auftreten, nämlich, dass es im Debugger nicht passiert.

Das heißt allerdings nicht, dass das Debuggen direkt mit dem Fehler zu tun hat. Es bedeutet nur, dass es diesen leichter oder schwerer nachstellbar macht.

Ein Punkt, der direkt die Delphi IDE betrifft:
Diese setzt mit timeBeginPeriod..timeEndPeriod systemweit die Timer-Auflösung herunter, ich glaube auf 1. Dadurch verhalten sich insbesondere Aufrufe von Sleep anders.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:52 Uhr.
Seite 2 von 3     12 3      

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