![]() |
Best Practice : ein Object in enem anderen Thread abfragen
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:
Danke schonmalWhile 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; |
AW: Best Practice : ein Object in enem anderen Thread abfragen
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. |
AW: Best Practice : ein Object in enem anderen Thread abfragen
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 |
AW: Best Practice : ein Object in enem anderen Thread abfragen
Ich würde ein BusyFlag als Integer spendieren, und mit
Delphi-Quellcode:
abfragen, sicherheitshalber.
function GetBusy : Boolean;
begin LRes := TInterlocked.Exchange( LThreadFlag, LThreadFlag); Result := LRes <> 0; end; 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. |
AW: Best Practice : ein Object in enem anderen Thread abfragen
Zitat:
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. |
AW: Best Practice : ein Object in enem anderen Thread abfragen
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 .. |
AW: Best Practice : ein Object in enem anderen Thread abfragen
Wenn du möchtest, dass ein Thread seine Arbeit beendet, dann rufe die Methode
![]() Innerhalb des Threads kannst du die Eigenschaft ![]()
Delphi-Quellcode:
) abfragen, ob es da einen Wunsch nach Beendigung gibt.
protected
Zusätzlich gibt es auch die Methode ![]() ![]() 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:
Der läuft jetzt so lange, bis man
procedure TMyThread.Execute;
begin while not Terminated do begin // mach was simuliertes Sleep(10); end; end; ![]() ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:40 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