AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Best Practice : ein Object in enem anderen Thread abfragen
Thema durchsuchen
Ansicht
Themen-Optionen

Best Practice : ein Object in enem anderen Thread abfragen

Ein Thema von MyRealName · begonnen am 25. Jan 2019 · letzter Beitrag vom 26. Jan 2019
Antwort Antwort
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
675 Beiträge
 
Delphi 10.4 Sydney
 
#1

Best Practice : ein Object in enem anderen Thread abfragen

  Alt 25. Jan 2019, 15:20
Ich habe in einem Service mehrere Datenbank threads (jeder kümmert sich um ene andere DB) und wenn ich diesen service runterfahren will, dann will ich sicherstellen, dass ich nicht in einem der threads gerade was tue. Ich weiss, dass Schreiben auf eine Variable in einem anderen Thread ganz sicher Probleme bringen kann, ist das mit Lesen genauso? Könnte ich dem Datanmodule, welches in einem anderen Thread nur genutzt wird, eine public property "Busy" verpassen, welche von ausserhalb gelesen werden kann ?

Wenn nicht, was wäre die beste (nicht asynchrone) Methode, um das zu erreichen.

Die Idee war sowas wie

Code:

While List.count > 0 do begin
  for item in List do
  begin
    If not Item.Busy then
    begin
      List.Remove(Item);
      Item.free;
    end
  end;
  If List.Count > 0
    Delay(100);
end;
Danke schonmal
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
702 Beiträge
 
Delphi 12 Athens
 
#2

AW: Best Practice : ein Object in enem anderen Thread abfragen

  Alt 25. Jan 2019, 15:34
Lesen ist normalerweise problemlos möglich, wenn die entsprechende Variable byte oder boolean ist, da sind operationen auf jeden Fall "atomisch" (können von einem Thread-switch nicht unterbrochen werden). Bei Variablen, die 2 oder 4 bytes belegen sind Operationen nur atomisch, wenn die Addresse der Variablen entsprechend aligned ist (d.h. eine Potenz von 2 bzw. 4). Bei Feldern in einem Objekt oder globalen Variablen sorgt der Compiler für eine entsprechendes Alignment.

In deinem Fall sollte also ein Busy flag (Boolean) keine Probleme machen, solange Dir nicht irgendein Code das Datenmodul selbst unter dem Hintern wegschießt .

Allerdings gibt es da immer noch Fallen. Wenn Du ein Flag aus Thread A liest, welches von Thread B gesetzt oder gelöscht werden kann, kann der gelesene Wert schon veraltet sein, bevor Thread A ihn verarbeiten kann. Ob das ein Problem sein kann hängt von den Details deines Scenarios ab.

Normalerweise geht man wie folgt vor:

Thread B (der Hintergrundthread) hat eine Arbeitsschleife, die bei jeder Runde prüft, ob die Terminated property des Threads true ist. Wenn ja wie Schleife verlassen und der Thread beendet sich. Thread A kann dann ThreadB.Terminate aufrufen, um das Flag zu setzen, und dann ThreadB.Waitfor, um zu warten, bis der Thread sich beendet hat. Man sollte aber auf jeden Fall einen sinnvollen Timeout an Waitfor übergeben, sonst wartet ThreadA eventuell ewig, wenn sich B aufgehängt hat.
Peter Below

Geändert von peterbelow (25. Jan 2019 um 15:42 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
675 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Best Practice : ein Object in enem anderen Thread abfragen

  Alt 25. Jan 2019, 15:49
Das mit dem terminate muss ich mal schauen, weil ich nutze zum Threading die RealThinClient Komponente TRtcQuickJob, da kann ich zwar nachsehen, ob jobs laufen, aber ich kann sie wohl nicht einfach unterbrechen und zwischen 2 jobs sagen : Mach mal nicht weiter, ich will den service runterfahren. Rein technisch kann ich aber sicher eine Nachricht an den thread message handler schicken. Mal basteln.

Danke Peter
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.094 Beiträge
 
Delphi 12 Athens
 
#4

AW: Best Practice : ein Object in enem anderen Thread abfragen

  Alt 25. Jan 2019, 16:35
Ich würde ein BusyFlag als Integer spendieren, und mit
Delphi-Quellcode:
function GetBusy : Boolean;
begin
  LRes := TInterlocked.Exchange( LThreadFlag, LThreadFlag);
  Result := LRes <> 0;
end;
abfragen, sicherheitshalber.
Was Peter schreibt stimmt schon, aber weil die Busy-Abfrage ja nicht permanent läuft würde ich mir da etwas mehr "Freiraum" drumrum schaffen,
damit nicht bei plötzlichen Änderungen des Typs aus Versehen etwas in die Hose geht.
  Mit Zitat antworten Zitat
Benutzerbild von MyRealName
MyRealName

Registriert seit: 19. Okt 2003
Ort: Heilbronn
675 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Best Practice : ein Object in enem anderen Thread abfragen

  Alt 25. Jan 2019, 18:24
Ich würde ein BusyFlag als Integer spendieren, und mit
Delphi-Quellcode:
function GetBusy : Boolean;
begin
  LRes := TInterlocked.Exchange( LThreadFlag, LThreadFlag);
  Result := LRes <> 0;
end;
abfragen, sicherheitshalber.
Was Peter schreibt stimmt schon, aber weil die Busy-Abfrage ja nicht permanent läuft würde ich mir da etwas mehr "Freiraum" drumrum schaffen,
damit nicht bei plötzlichen Änderungen des Typs aus Versehen etwas in die Hose geht.
Das mit dem Exhange geht nicht, da es keine Object properties annimmt und da ich mehrere Instanzen des Objects habe, kann ich keine globale variable nehmen.
Im moment mache ich das setzen von aussen mit critical sections, das lesen ohne. Von innen (im thread) wird es nur gelesen, nur beim erzeugen einmal auf False gesetzt.
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.094 Beiträge
 
Delphi 12 Athens
 
#6

AW: Best Practice : ein Object in enem anderen Thread abfragen

  Alt 25. Jan 2019, 18:33
Ich meinte ja auch ein Flag pro Objektinstanz, um das Busy der jeweiligen
Instanz zu entkoppeln.
So hatte ich dich verstanden, das du jede Thread-Instanz einzeln abfragen möchtest.

Delphi-Quellcode:
function TDeinThreadObject.GetBusy : Boolean;
begin
..
  Mit Zitat antworten Zitat
Schokohase
(Gast)

n/a Beiträge
 
#7

AW: Best Practice : ein Object in enem anderen Thread abfragen

  Alt 26. Jan 2019, 09:16
Wenn du möchtest, dass ein Thread seine Arbeit beendet, dann rufe die Methode Delphi-Referenz durchsuchenTThread.Terminate auf.

Innerhalb des Threads kannst du die Eigenschaft Delphi-Referenz durchsuchenTThread.Terminated (protected ) abfragen, ob es da einen Wunsch nach Beendigung gibt.

Zusätzlich gibt es auch die Methode Delphi-Referenz durchsuchenTThread.TerminatedSet die man überschreiben kann. Diese wird beim erstmaligen Aufruf von Delphi-Referenz durchsuchenTThread.Terminate aufgerufen.

Grundsätzlich entscheidet der Thread immer selber ob er sich nun beendigt oder nicht, denn nur der Thread selber weiß um seinen Zustand und wann dieser gefahrlos verlassen werden kann.

Eine simple Execute-Methode in einem Thread sieht z.B. so aus:
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
  while not Terminated do
  begin
    // mach was simuliertes
    Sleep(10);
  end;
end;
Der läuft jetzt so lange, bis man Delphi-Referenz durchsuchenTThread.Terminate aufruft (was im Übrigen von Delphi-Referenz durchsuchenTThread.Destroy intern auch aufgerufen wird).
  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 01:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz