![]() |
TThread.Synchronize prophylaktisch verwenden
Ich habe noch nicht so viel mit Threads gemacht, deshalb brauche ich eure Meinung.
Ich habe eine Klasse die verschiedene Methoden hat, die länger dauern "können". Die Klasse wurde bisher nie innerhalb eines Threads verwendet. Im DoNotify kann alles mögliche aufgerufen werden. Auch Bildschirmaktualisierungen. Der Code innerhalb der aufrufenden Methoden (LongTimePart1 etc.) ist threadsicher. Aber durch den Aufruf von DoNotify kann ich die ganze Methode nicht als threadsicher ansehen. Daher sehe ich die ganze Klasse nicht als threadsicher an. Nun möchte ich die Procedure LongTimePart1 innerhalb eine Threads aufrufen. Da LongTimePart1 nicht threadsicher ist, müsste ich diese innerhalb eines Thread.Synchronize aufrufen. Dann würde aber auch "Mach Viel" im Hauptthread laufen. Nun mein Gedankengang: Kann ich nicht einfach DoNotify threadsicher machen, in dem ich prophylaktisch dort Thread.Synchronize verwende? Dann wäre die ganze Klasse threadsicher. Nun kann es aber sein, dass die Procedure LongTimePart1 im Hauptthread aufgerufen wird. Nun weis ich nicht, ob es Probleme gibt, wenn Thread.Synchronize nicht innerhalb eines Threads aufgerufen wird sondern im Hauptthread. Wie ist eure Meinung?
Delphi-Quellcode:
// Dieser Code ist ein stark verkürzter Beispielcode type TWorkerTest = class(TObject) private FOnNotify: TNotifyEvent; public property OnNotify: TNotifyEvent read FOnNotify write FOnNotify; Procedure DoNotify; public Procedure LongTimePart1; Procedure LongTimePart2; Procedure LongTimePart3; end; implementation { TWorkerTest } procedure TWorkerTest.DoNotify; begin //****************************************** // bestehende Version - Nicht threadsicher // // if assigned(FOnNotify) then // FOnNotify(self); //****************************************** // neue Version - hoffentlich threadsicher // Die Methoden, welche OnNotify verwenden, // "können" aus einem Thread aufgerufen sein. Müsse aber nicht. TThread.Synchronize(nil, procedure begin if assigned(FOnNotify) then FOnNotify(Self); end); end; procedure TWorkerTest.LongTimePart1; begin // Mach viel. Threadsicherer Code. DoNotify; end; procedure TWorkerTest.LongTimePart2; begin // Mach viel. Threadsicherer Code. DoNotify; end; procedure TWorkerTest.LongTimePart3; begin // Mach viel. Threadsicherer Code. DoNotify; end; |
AW: TThread.Synchronize prophylaktisch verwenden
Zumindest in neueren delphis kannst du das beruhigt auch im hauptthread aufrufen, da es gegebenenfalls dann direkt aufgerufen wird.
|
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
![]() Falls du mehrere Stunden erübrigen kannst, bietet sich dieses Buch von Dalija Pasnikar an: ![]() |
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
Hat mir aber nicht direkt die Frage beantwortet, ob ich Thread.Synchronize unbedenklich im Hauptthread aufrufen kann. Zitat:
|
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
Und ![]() Zitat:
|
AW: TThread.Synchronize prophylaktisch verwenden
Leider hat TThread.Queue auch dieses Verhalten
und anstatt es zu reparieren, damit die Funktion immer das macht, wie sie heißt, wurde TThread.ForceQueue erfunden, welches sich auch im Hauptthread "richtig" verhält. Fazit: Einfach immer ForceQueue statt Queue verwenden. |
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
|
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
|
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
Sie wurde schon immer innerhalb eines Threads verwendet, nämlich des mainthreads. :stupid: /klugscheissermodus off Was ich damit sagen will: deine Änderung macht das nun nicht per se threadsicher sondern sorgt nur dafür, dass OnNotify immer im Mainthread ausgeführt wird. Das muss man dann beim Verwenden wissen. Es wird bei dir vermutlich nicht der Fall sein, da du ja laut deiner Aussage noch nie etwas in einem Nebenthread gemacht hast, aber generell ist man nicht dadurch sicher, dass man Code mit TThread.Synchronize in den Mainthread verschiebt. Denn auch dort kann dann Code ausgeführt werden, der mit einem anderen Nebenthread eine race condition erzeugt. |
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
Zitat:
|
AW: TThread.Synchronize prophylaktisch verwenden
Wenn ALLE Codes, welche auf das Gleiche zugreifen, im Hauptthread (bzw. immer nur im selben Thread) werkeln, dann wäre es quasi sicher, da immer nur Einer gleichzeitig kann.
Eine Alternative wären z.B. CriticalSections, damit auch zwischen mehreren Threads immer nur Einer kann. |
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
Delphi-Quellcode:
if Windows.GetCurrentThreadId = MainThreadID then
Mavarik :coder: |
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
Aber wie ich schon gelernt habe, kontrolliert Thread.Synchronize selber, ob er sich im Mainthread befindet. |
AW: TThread.Synchronize prophylaktisch verwenden
Vieles in der Windows.pas ist inzwischen auch für andere Platformen verfügbar.
Delphi-Quellcode:
,
if Windows.GetCurrentThreadId = TThread.CurrentThread.ThreadID then
aber TThread.Current, bzw. TThread.CurrentThread ist selbst schon irgendwie pervers, um damit nur auf die ID zureifen zu wollen. |
AW: TThread.Synchronize prophylaktisch verwenden
Du kannst dir auch TThread.Current bei der Zuweisung deiner Notifier merken und bei TThread.Synchronize statt nil übergeben. Das kommt auf deine Threadarchitektur an. Voraussetzung wäre ja, dass der andere Thread entsprechend lange existiert. Dann müsste das aber nicht der Hauptthread sein, den du mit nil ansprichst.
Threads kannst du wirklich auf sehr viele Arten verwenden. Wichtig ist, dass du einen Plan hast, wann welcher Thread gestartet und beendet wird, was in welchem Kontext ausgeführt werden muss, welcher Kontext wie lange lebt, und wer sich um die Beendigung deiner Threads kümmert. Teilweise wird dir das abgenommen (Tasks, PPL, anonyme Threads, ...), teilweise musst du das alles manuell machen (TThread, ...). |
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
|
AW: TThread.Synchronize prophylaktisch verwenden
FWIW
Delphi-Quellcode:
für "nicht-Windows" ist definiert in Posix.Pthread.pas
GetCurrentThreadId
|
AW: TThread.Synchronize prophylaktisch verwenden
Zitat:
Ist noch ein weiter Weg. Kennst du ja ;-) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:34 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