Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi TThread.Synchronize prophylaktisch verwenden (https://www.delphipraxis.net/216801-tthread-synchronize-prophylaktisch-verwenden.html)

bernau 5. Mär 2025 08:23


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;

Olli73 5. Mär 2025 08:29

AW: TThread.Synchronize prophylaktisch verwenden
 
Zumindest in neueren delphis kannst du das beruhigt auch im hauptthread aufrufen, da es gegebenenfalls dann direkt aufgerufen wird.

Uwe Raabe 5. Mär 2025 08:42

AW: TThread.Synchronize prophylaktisch verwenden
 
Zitat:

Zitat von bernau (Beitrag 1546812)
Ich habe noch nicht so viel mit Threads gemacht, deshalb brauche ich eure Meinung.

Ist jetzt zwar ein wenig Eigenwerbung, aber vielleicht investierst du mal ein paar Minuten zum Lesen dieses Artikels: Async Tasks in VCL Projects

Falls du mehrere Stunden erübrigen kannst, bietet sich dieses Buch von Dalija Pasnikar an: Delphi Event-based and Asynchronous Programming

bernau 5. Mär 2025 09:17

AW: TThread.Synchronize prophylaktisch verwenden
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1546816)

Ist jetzt zwar ein wenig Eigenwerbung, aber vielleicht investierst du mal ein paar Minuten zum Lesen dieses Artikels: Async Tasks in VCL Projects

Ja. Schon gelesen. Sehr interessant, wie alles aus deinem Blog ;-)

Hat mir aber nicht direkt die Frage beantwortet, ob ich Thread.Synchronize unbedenklich im Hauptthread aufrufen kann.



Zitat:

Zitat von Uwe Raabe (Beitrag 1546816)
Falls du mehrere Stunden erübrigen kannst, bietet sich dieses Buch von Dalija Pasnikar an: Delphi Event-based and Asynchronous Programming

Danke für den Link.

bernau 5. Mär 2025 09:37

AW: TThread.Synchronize prophylaktisch verwenden
 
Zitat:

Zitat von Olli73 (Beitrag 1546814)
Zumindest in neueren delphis kannst du das beruhigt auch im hauptthread aufrufen, da es gegebenenfalls dann direkt aufgerufen wird.

Danke.

Und hier habe ich auch die Bestätigung gefunden

Zitat:

Zitat von docwiki.embarcadero.com
Hinweis: Der Aufruf von Synchronize aus dem Haupt-Thread ist sicher.


himitsu 5. Mär 2025 10:14

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.

Uwe Raabe 5. Mär 2025 10:24

AW: TThread.Synchronize prophylaktisch verwenden
 
Zitat:

Zitat von himitsu (Beitrag 1546821)
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.

Die Krux mit dem Reparieren ist halt oft ein inkompatibles Verhalten bei bestehendem Code, der sich auf das falsche verlässt.

QuickAndDirty 5. Mär 2025 11:05

AW: TThread.Synchronize prophylaktisch verwenden
 
Zitat:

Zitat von himitsu (Beitrag 1546821)
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.

Ja ForceQueue ist echt super hilfreich! Da man selber nie weiß in welcher reihenfolge Ereigniss von Userinput erfolgen kommt das bei mir in fast jedes klick ereignis...damit das rendern von irgend einem effekt nicht durch meinen Code unterbrochen wird...

Stevie 5. Mär 2025 11:26

AW: TThread.Synchronize prophylaktisch verwenden
 
Zitat:

Zitat von bernau (Beitrag 1546812)
Die Klasse wurde bisher nie innerhalb eines Threads verwendet.

/klugscheissermodus on

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.

bernau 5. Mär 2025 11:42

AW: TThread.Synchronize prophylaktisch verwenden
 
Zitat:

Zitat von Stevie (Beitrag 1546827)
/klugscheissermodus on -> mainthread

:lol:



Zitat:

Zitat von Stevie (Beitrag 1546827)
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.

Stimmt. Darüber habe ich noch gar nicht nachgedacht. Gut zu wissen.


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