AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Thread.Queue, Zeitmessung, Thread hängt angeblich
Thema durchsuchen
Ansicht
Themen-Optionen

Thread.Queue, Zeitmessung, Thread hängt angeblich

Ein Thema von AJ_Oldendorf · begonnen am 20. Mai 2025 · letzter Beitrag vom 26. Mai 2025
Antwort Antwort
Edelfix

Registriert seit: 6. Feb 2015
Ort: Stadtoldendorf
251 Beiträge
 
Delphi 12 Athens
 
#1

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

  Alt 23. Mai 2025, 10:49
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
  Mit Zitat antworten Zitat
Edelfix

Registriert seit: 6. Feb 2015
Ort: Stadtoldendorf
251 Beiträge
 
Delphi 12 Athens
 
#2

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

  Alt 23. Mai 2025, 11:01
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.
  Mit Zitat antworten Zitat
AJ_Oldendorf

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

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

  Alt 23. Mai 2025, 11:33
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:

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
  Mit Zitat antworten Zitat
AJ_Oldendorf

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

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

  Alt 23. Mai 2025, 11:34
Ü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.
  Mit Zitat antworten Zitat
QuickAndDirty

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

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

  Alt 23. Mai 2025, 12:00
Ü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?
Andreas
Nobody goes there anymore. It's too crowded!
  Mit Zitat antworten Zitat
AJ_Oldendorf

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

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

  Alt 23. Mai 2025, 12:14
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

Geändert von AJ_Oldendorf (23. Mai 2025 um 12:16 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.052 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#7

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

  Alt 23. Mai 2025, 12:17
Kann es sein das LLVM Threads auf eine seltsameweise dealociert?
Was hat LLVM mit ner 64bit VCL Anwendung zu tun?

Ü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 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.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (23. Mai 2025 um 12:19 Uhr)
  Mit Zitat antworten Zitat
AJ_Oldendorf

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

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

  Alt 23. Mai 2025, 12:40
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 OutputDebugString('SAMPLING ON') aufrufen, zu dem Zeitpunkt vor dem Hänger und 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
  Mit Zitat antworten Zitat
QuickAndDirty

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

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

  Alt 23. Mai 2025, 12:57
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.
Andreas
Nobody goes there anymore. It's too crowded!
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz