Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TThread: Daten von Mainthread holen --> Synchronize notwendig? (https://www.delphipraxis.net/216377-tthread-daten-von-mainthread-holen-synchronize-notwendig.html)

Helmi 18. Dez 2024 07:22

TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Hallo Zusammen,

wenn man in einem Thread etwas an den Mainthread/VCL/GUI schicken möchte, dann muss man
Delphi-Quellcode:
Synchronize
verwenden.
Ist dies auch notwendig, wenn man sich Daten aus dem Mainthread holt?

In meinem Falle lasse ich mir einen String übergeben.
Dazu hab ich in der Thread-Unit eine function, die eine function im Mainthread aufruft und über die wird der String übergeben.

jaenicke 18. Dez 2024 07:29

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Du musst den Zugriff absichern, aber du kannst auch einfach TMonitor verwenden:
Delphi-Quellcode:
TMonitor.Enter(MyThread); // oder ein anderes Objekt
try
  MyThread.Value := 'Test';
finally
  TMonitor.Exit(MyThread);
end;
Wenn du jeden Zugriff auf den Wert (Schreiben + Lesen) so absicherst, brauchst du kein Synchronize, was viel aufwendiger ist.

Synchronize brauchst du nur, wenn du etwas wirklich im Kontext eines anderen Threads durchführen musst. Dazu zählt z.B. eine Callback-Funktion, die aus einem Threrad aufgerufen wird, und z.B. auf eine Datenbank oder die GUI zugreifen möchte. Wenn du lediglich die Zugriffe absichern musst, ist das nicht nötig.

Und wenn ein Wert oft gelesen, aber nur selten geschrieben wird, gibt es noch den TMultiReadExclusiveWriteSynchronizer, der dies optimiert. Da ist dann lediglich die (seltene) Schreiboperation teuer, aber das Lesen geht schnell.

Rollo62 18. Dez 2024 07:51

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Hier etwas alternativer Lesestoff zu TThreadedQueue über die Weihnachtszeit, TL;DR :-D

https://ideasawakened.com/post/revis...itor-in-delphi
https://en.delphipraxis.net/topic/28...-and-tmonitor/

Helmi 18. Dez 2024 08:26

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Zitat:

Zitat von jaenicke (Beitrag 1544411)
Du musst den Zugriff absichern, aber du kannst auch einfach TMonitor verwenden:
Delphi-Quellcode:
TMonitor.Enter(MyThread); // oder ein anderes Objekt
try
  MyThread.Value := 'Test';
finally
  TMonitor.Exit(MyThread);
end;
Wenn du jeden Zugriff auf den Wert (Schreiben + Lesen) so absicherst, brauchst du kein Synchronize, was viel aufwendiger ist.

Wenn ich dich jetzt (hoffentlich) richtig versteh, dann reicht es aus, im Mainthread/GUI in den proceduren, die vom Thread aufgerufen werden, jeweils TMonitor aufzurufen, in dem dann z. B. der String an den Thread übergeben wird, bzw. z. B. die GUI mit den Daten versorgt wird, die vom Thread kommen?

jaenicke 18. Dez 2024 09:29

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Du musst alle Zugriffe entsprechend absichern. Beispiel:
Delphi-Quellcode:
// Hauptthread:
TFormA = class(TForm)
private
  FValue: string;
...
end;

procedure TFormA.Example;
begin
  TMonitor.Enter(Self);
  try
    FValue := 'Test';
  finally
    TMonitor.Exit(Self);
  end;
end;

// vom Thread aufgerufen:
function TFormA.ThreadCallback: string;
begin
  TMonitor.Enter(Self);
  try
    Result := FValue;
  finally
    TMonitor.Exit(Self);
  end;
end;

Helmi 18. Dez 2024 10:31

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Zitat:

Zitat von jaenicke (Beitrag 1544415)
Du musst alle Zugriffe entsprechend absichern. Beispiel:

Dank dir - dann hatte ich es richtig verstanden.
Auf das Synchronize hab ich Thread kann ich dann verzichten

Bei mir schauts dann so aus:
Delphi-Quellcode:
procedure TMainForm.Thread_UDP_ReceiveString(var Text: String);
begin
  Text := '';

  System.TMonitor.Enter(ClientThread);

  try
    If idUDPClient.Connected then
      Text := IdUDPClient.ReceiveString(-1, TEncoding.UTF8);

  finally
    System.TMonitor.Exit(ClientThread);
  end;
end;

procedure TMainForm.Thread_Daten(const Text: String);
begin
  System.TMonitor.Enter(ClientThread);

  try
    InfoForm.InfoText := Text;
  finally
    System.TMonitor.Exit(ClientThread);
  end;
end;

himitsu 18. Dez 2024 11:29

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Jupp, natürlich all, auch die innerhalb des Hauptthreads.

Zitat:

Delphi-Quellcode:
System.TMonitor

Und den Namespace, weil die Idioten dieses TMonitor blind eingebaut hatten, nachdem es schon Jahrzehnte lang bereits ein anderes TMonitor gab/gibt, was aber was ganz anderes ist (Bildschirme).

Beim Syncronize und Queue mußt du nur alles in Threads absichern rüberschieben, in den Hauptthread, was nicht im Hauptthread ist, dann das im Hauptthread ist ja bereits dort.

Und für Integer/Int64/Cardinal/UInt64/Word/LongBool und andere 2, 4 bzw. 8 Byte große "einfache" Typen, wie z.B. ENUMs, gibt es auch Funktionen aus CPU-Ebene Systemebene,
wo beim Schreiben alle anderen Schreib- und Lesevorgänge gesperrt/pausiert sind.

Delphi-Referenz durchsuchenInterlockedExchange oder besser Delphi-Referenz durchsuchenAtomicExchange
InterlockedCompareExchange / AtomicCmpExchange
InterlockedExchange64
InterlockedExchangePointer
InterlockedDecrement / AtomicDecrement
InterlockedIncrement / AtomicIncrement
uvm.

Helmi 18. Dez 2024 11:37

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Zitat:

Zitat von himitsu (Beitrag 1544423)
Jupp, natürlich all, auch die innerhalb des Hauptthreads.

Zitat:

Delphi-Quellcode:
System.TMonitor

Und den Namespace, weil die Idioten dieses TMonitor blind eingebaut hatten, nachdem es schon Jahrzehnte lang bereits ein anderes TMonitor gab/gibt, was aber was ganz anderes ist (Bildschirme).

Dachte zuerst, dass mein XE2 noch nicht TMonitor für Threads kennt, bis ich irgendwo gelesen hab, dass es das seit 2009 gibt.
Bin auch anfangs erst mal bei Bildschirme rausgekommen, daher System.TMonitor.

Zitat:

Zitat von himitsu (Beitrag 1544423)
Beim Syncronize und Queue mußt du nur alles in Threads absichern rüberschieben, in den Hauptthread, was nicht im Hauptthread ist, dann das im Hauptthread ist ja bereits dort.

Ich hab jetzt mehrmals den Satz gelesen und habe mehrmals nicht verstanden, was du mir damit sagen willst.

TomyN 18. Dez 2024 14:35

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Hi,

Ich hänge mich mal hier mit dran. Normalerweise synchronisiere ich mit einer Mutex oder einer CriticalSection.
Was sind da die Unterschiede? Beim TMonitor brauch ich wohl keine globale variable für die Mutex oder?

jaenicke 18. Dez 2024 17:38

AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
 
Zitat:

Zitat von Helmi (Beitrag 1544420)
Bei mir schauts dann so aus:
Delphi-Quellcode:
procedure TMainForm.Thread_UDP_ReceiveString(var Text: String);
begin
  Text := '';

  System.TMonitor.Enter(ClientThread);

  try
    If idUDPClient.Connected then
      Text := IdUDPClient.ReceiveString(-1, TEncoding.UTF8);

  finally
    System.TMonitor.Exit(ClientThread);
  end;
end;

Dann führst du das ReceiveString aber auch innerhalb des Locks aus, obwohl es dafür gar keinen Grund gibt. Besser ist es, wenn du alles fertig machst und dann nur noch in dem abgesicherten Teil die Zielvariable schreibst.

Denn je länger du Threads blockierst, desto eher übersiehst du mögliche Deadlocks, sprich dass sich zwei Threads gegenseitig blockieren, weil beide auf den anderen warten (z.B. einer im TMonitor.Enter, der andere in einem Synchronize, jetzt nur als Beispiel). Die Gefahr besteht hier nicht, aber trotzdem sollte man in einem Lock, sprich hier zwischen Enter und Exit, so wenig Code wie möglich ausführen.

Zitat:

Zitat von TomyN (Beitrag 1544432)
Ich hänge mich mal hier mit dran. Normalerweise synchronisiere ich mit einer Mutex oder einer CriticalSection.
Was sind da die Unterschiede? Beim TMonitor brauch ich wohl keine globale variable für die Mutex oder?

TMonitor funktioniert über eine Objektreferenz. Auf die brauchst du also auch Zugriff. Innerhalb eines Objekts geht das mit Self sehr einfach.

Eine TCriticalSection ist tendentiell etwas schneller, ein Mutex sehr viel langsamer, da dieser über den Kernel läuft. Einen Mutex sollte man nur zur Interprozesskommunikation nutzen, nicht innerhalb eines Prozesses.

Wenn es um beste Performance geht, ist eine TCriticalSection meistens am besten. Wenn du das bisher so machst, ist das völlig in Ordnung. TMonitor ist aber einfacher zu nutzen, wenn man im Kontext eines Objekts ist, weshalb ich das trotzdem gerne nutze. Bei den meisten Anwendungsfällen wird der Performanceunterschied keine Rolle spielen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:21 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 by Thomas Breitkreuz