Delphi-PRAXiS
Seite 7 von 9   « Erste     567 89      

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)

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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:44 Uhr.
Seite 7 von 9   « Erste     567 89      

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