![]() |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Ich glaube nicht, dass die Spekulation über atomare Instruktionen in Bezug auf die gestellte Frage Sinn macht.
In DP geht es im Wesentlichen um Delphi, also um eine Hochsprache, die Umgebung sollte man generell als Black Box betrachten. Somit kann man definieren: Zitat:
wenn das Programm nur Komponenten verwendet, die ihrerseits thread-sicher sind. wenn der Zugriff und die Veränderung gemeinsam verwendeter Zustände aus geregelte Weise erfolgt. P.S. Übrigens gibt es eine Komponente System.SysUtils.TMultiReadExclusiveWriteSynchroniz er |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Zitat:
![]() |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
@Mikkey&Olli73
Danke, genau das meinte ich. :thumb: |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Zitat:
Es ging ja darum, gemeinsamenm Speicher gleichzeitig bearbeiten zu können. Dass jeder Thread seinen eigenen Speicher bekommt, wäre mit jeder Architektur mit unterschiedlichen Variablen nicht sonderlich schwer zu lösen... |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Zitat:
Das war ja auch nur wegen MultiCore und alle teilen sich einen Arbeitsspeicher :) |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Zitat:
Bei mir gibt es eine Klasse "TThreadExecuter" .. die bekommt einfach einen MethodenPointer und ruft zyklisch wie ein Timer einen MethodenPointer der gewünschten Klasseauf. Meist 1 ms mit Sleep(1) .. aber oft ist das gar nicht notwendig. So wird eine Funktion, die sich meistens ähnlich schimpft wie "CyclicMainJobs/ CyclicThreadProc" in einem anderen Thread aufgerufen. Bei Bedarf kann der Aufruf auch schnell alternativ von einem "TTimerExecuter" durchgeführt werden, so wird anstatt eines zweiten Threads die Methode einfach von Hauptthread aus mit einem Timer aufgerufen. Das Ganze hat den Vorteil, dass man auf alle Variablen der Klasse ohne Umstände Zugriffe hat. Und das Ganze auch mehr zur "asynchronen" Eventverarbeitung tendiert und mit modernen OOP Konzepten gemeinsam harmoniert, als so eine popelige Schleife lediglich in der abgeleiteten Execute Procedure- Mit einer übergebenen Instanz einer "SyncKlasse" können auch "teil-global" mehrere Objecte miteinander synchronisiert werden. Das nur mal als "Brainstorming Idee".... Aufpassen muss man natürlich, und genau drauf achten, welche Methoden von einem anderem als dem Hauptthread aufgerufen werden ..(werden können).. um dann sauber und ohne Fehler entsprechende Abschnitte im Code zu locken.. |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Zitat:
Und welche Klasse meinst Du mit 'der gewünschten Klasse'? Und ist der 'Methodenpointer' in der 'gewünschten Klasse' nicht ein Verstoß gegen ![]() Wie verhält es sich mit dem ![]() Ich finde einen Workerthread(pool) mit Jobs, die man definiert, implementiert und den Arbeitern zur Verarbeitung gibt, immer noch am elegantesten. Man hat einen Pool pro Anwendung und schmeisst da die Jobs rein, fertig... ne, wie sagt der Fachmann :mrgreen: und schon ist der Drops gelutscht. |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Zitat:
Ich würde die Klasse nicht ThreadExecuter, sondern lieber "TSaugdenAkkuleer" oder "TCPUCycleKiller" nennen... Dafür gibt es doch Waitfor oder Multisyncwait damit der Thread schläft so lange er nicht gebraucht wird. Mavarik PS.: Ich habe mir hierfür eine mini Unit gemacht die so was erledigt.
Delphi-Quellcode:
unit UseMyThread;
interface Uses System.Classes,System.SysUtils,System.SyncObjs,System.Generics.Collections; type TMyThread = class(TThread) Private FRunning : boolean; E_Event : TEvent; Protected Procedure Execute;override; Public Constructor Create; Destructor Destroy;override; procedure Terminate; reintroduce; virtual; Procedure MyExecute;Virtual;Abstract; Procedure MyFree;Virtual;Abstract; Procedure Go; end; // ProcessorCount implementation { TMyThread } constructor TMyThread.Create; begin inherited Create(true); E_Event := TEvent.Create(NIL,false,false,''); FRunning := false; FreeOnTerminate := false; end; destructor TMyThread.Destroy; begin Terminate; inherited; try MyFree; except end; try E_Event.Free; except end; end; procedure TMyThread.Execute; begin while not(Terminated) do begin try FRunning := false; // Atom ? E_Event.WaitFor(INFINITE); if Terminated then exit; FRunning := true; MyExecute; except end; end; end; procedure TMyThread.Go; begin if not(Started) then Start; E_Event.SetEvent; end; procedure TMyThread.Terminate; begin inherited Terminate; E_Event.SetEvent; end; end. |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Zitat:
Eine Frage zu deinem Code: Hast Du schon mal was von Fail Fast gehört, oder einfach ausgedrückt: "Ordentliches Exception Handling"? Dein "An die Wand gefahren? Merkt doch keiner" ist eventuell schwierig beim Finden von Fehlern. Noch eine Frage: Wo ist der Mehrwert der Methode 'Go' ggü 'Resume'? Klar, der Aufruf von 'Suspend' ist ein No-Go, aber ansonsten? |
AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
@Frank
Den Thread im Suspended-Mode zu starten macht irgendwie keinen Sinn, da der doch schon durch den Event wartet. Ich würde auch nicht
Delphi-Quellcode:
überschreiben, sondern
TThread.Terminate
Delphi-Quellcode:
, denn das ist schon als
Tthread.TerminatedSet
Delphi-Quellcode:
deklariert und somit zum Überschreiben gedacht.
virtual
Die Klasse selber würde ich noch als
Delphi-Quellcode:
deklarieren (nur wegen der Dokumentation), denn ohne Ableitung ist die ja so nicht lauffähig.
abstract
Einfach so die Exception wegfangen ist auch nicht gerade schön, und wenn fangen, dann nur so:
Delphi-Quellcode:
Das hier
try
MyExecute; except // Nur spezielle Exceptions fangen, die MyExecute bewusst ausgelöst hat // Alle anderen unvorhergesehenen werden durchgereicht on E:MyExecuteException do begin end; end;
Delphi-Quellcode:
ist auch unsauber. Wenn meine Klasse nicht funktioniert, dann möchte ich die Fehler um die Ohren geschlagen bekommen.
try
E_Event.Free; except end; Bei dem
Delphi-Quellcode:
und
MyExecute
Delphi-Quellcode:
sieht das etwas anders aus, da hierfür nicht die Klasse
MyFree
Delphi-Quellcode:
zuständig ist.
TMyThread
Aber was passiert denn, wenn in
Delphi-Quellcode:
ein übler Fehler passiert (StackOverflow)?
MyExecute
Der Code kann immer wieder ausgeführt werden, ohne jeden Hinweis auf den Fehler. Das
Delphi-Quellcode:
im Destructor ist überflüssig (wird schon implizit vom
Terminate
Delphi-Quellcode:
aufgerufen ... ach nee, bei dir ja nicht ;))
inherited
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:19 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