![]() |
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:
verwenden.
Synchronize
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. |
AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
Du musst den Zugriff absichern, aber du kannst auch einfach TMonitor verwenden:
Delphi-Quellcode:
Wenn du jeden Zugriff auf den Wert (Schreiben + Lesen) so absicherst, brauchst du kein Synchronize, was viel aufwendiger ist.
TMonitor.Enter(MyThread); // oder ein anderes Objekt
try MyThread.Value := 'Test'; finally TMonitor.Exit(MyThread); end; 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. |
AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
Hier etwas alternativer Lesestoff zu TThreadedQueue über die Weihnachtszeit, TL;DR :-D
![]() ![]() |
AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
Zitat:
|
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; |
AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
Zitat:
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; |
AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
Jupp, natürlich all, auch die innerhalb des Hauptthreads.
Zitat:
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. ![]() ![]() InterlockedCompareExchange / AtomicCmpExchange InterlockedExchange64 InterlockedExchangePointer InterlockedDecrement / AtomicDecrement InterlockedIncrement / AtomicIncrement uvm. |
AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
Zitat:
Bin auch anfangs erst mal bei Bildschirme rausgekommen, daher System.TMonitor. Zitat:
|
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? |
AW: TThread: Daten von Mainthread holen --> Synchronize notwendig?
Zitat:
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:
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. |
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