![]() |
Re: Thread - Synchronize - 2 Forms - Verständnisproblem
Hallo,
vielen Dank erstmal, ich kau das erst mal durch und muss es verdauen. Mfg Dirk |
Re: Thread - Synchronize - 2 Forms - Verständnisproblem
Hallo Blub
nochmals danke für deine Ausführung. Ich habe da aber so meine Verständnissprobleme oder besser gesagt das so in meinem projekt umzusetzen. Mit der Abgrenzung der Variablen und Proceduren habe ich befolgt, leuchtet ja auch ein da sie sonst überall verfügbar sind und ich denke mal es auch konflikte mit Namensgleichheit geben kann. Ich habe ein wenig gegoogelt und versucht das mit den Variablen in einem Thread zu verstehen und es giebt da wiedersprüchliche Meinungen hinsichtlich des zugriffs auf Variablen ausserhalb eines Thread's. Manche sagen jeder Zugriff ob schreiben oder lesen muss abgesichert werden ander wiederung nur das scheiben da bei lesezugriffe keine werte verändert werden und auch nur den wenn mehrere Thread in gleiche Variable schreiben. Wie schon gesagt benutzen ich einen Record der alle informationen für die Steuerung enthält. Die dort abgespeicherten Daten werden jeweils nur von einem thread veränder, alle ander höhlen sich zu gegebener Zeit die Daten um damit wiederum ihre Berechnungen durchzuführen und legt das Ergebnis in seine eigens für sich reservierten Variable ab damit andere Thread sie sich dort wieder holen können. Klingt warscheinlich alles etwas kaotisch, aber ich habe hin und her überlegt wie ich eine Ablaufsteuerung hinbekomme, so das alle Module (Procsesse) selbstständig laufen ohne auf ein bestimmtes Ergebnis eine anderen Modul (Thread) zu warten, dass Hauptformular hat nur noch die Aufgabe auf Eingaben von aussen zu warten. Das Programm läuft zwar auf meine Rechner stabil und störungsfrei ich möchte natülich konflikte weitestgehend ausschliessen. Ich muss noch dazu sagen das ich in der Programmierung mit Delphi ein Neuling bin, bisher habe ich hauptsächlich mich mit Microcontroller beschäftigt. Hättest du eine Idee wie ich eine Rückmeldung in einen Thread machen kann wenn ein Benutzer einen Button oder eine Trackbar betätigt (bisher habe ich das auch über Variablen gemacht, geht auch) da der Thread diese informationen verarbeiten soll. Eine message denke ich geht nicht die müssten dann ja in mengen verschickt werden solange wie die Trackbar bedient wird. Die Sache mit der VCL Aktualiesierng per PostMessage gefällt mir zwar ser gut bekomme ich aber irgendwie nicht hin (Fensterhandle). Die Form für die Visualisierung werden zur Laufzeit erstellt je nach Bedarf und Menge. Auch zur Laufzeit kann sich das noch durch Benutzereingabe ändern. Giebt es eigendlich auch eine möglichkeit Message zu versenden ohne Handle wo jeder diese empfängt und je nach Parameter dann die Daten für sich in anspruch nimmt. Jetzt will ich deine Gedult mit meinen Problemen nicht überstrapazieren. MfG Dirk PS: Ich kann dir ja das Prog mal als lauffähige Variante zumailn damit du eine Vorstellung hast wass ich da treibe. Vieleicht erklären sich dann meine Probleme besser. |
Re: Thread - Synchronize - 2 Forms - Verständnisproblem
Hallo Dustin,
sobald ein Thread in eine Speicherbereich schreibt und ein anderer Thread diesen liest, muss dieser Bereich geschützt werden. Nur wenn überhaupt kein Schreibzugriff erfolgt, kann darauf verzichtet werden. Genaue Beschreibung gibts in der Delphihilfe: -> TCriticalSection -> TMultiReadExclusiveWriteSynchronizer Die Entwicklung des Anwendungsaufbaus kann ich dir nicht abnehmen, da ich die konkreten Anforderungen an dein Projekt nicht kenne. Hier ein par Anregungen: Ich würde jeden möglichen Prozessabschnitt als eigenständige Klasse erstellen. Der Prozessabschnitt sollte eine Liste von Schnittstellen bereitstellen, die Eingabeparameter entgegen nehmen oder Ausgabewerte bereitstellen. Der Abschnitt kann sich bei Bedarf einen Thread erstellen, der bestimmte Aufgaben erfüllt. Dazu werden Eingabeparameter an threadsichere Property übergeben. Auf Änderungen des Status/Ergebniss wird indirekt reagiert. Der Thread schickt eine Botschaft an das Hauptformular, daß diese an den entsprechenden Prozessabschnitt übergibt. Dieser liest den Status/Ergebniss über threadsichere Property und informiert die Ausgabeschnittstellen. Alternativ könnte der Thread diese Aufgabe übernehmen, dafür müssen die Schnittstellen aber dann threadsicher sein. Eine andere Möglichkeit, der Thread setzt bei Änderungen ein Property auf True, im Hauptthread werden über einen globalen Timer alle Prozessabschnitte zur Aktualisierung aufgefordert, der Thread reagiert auf das Property und setzt wieder False. Die Erstellung und Verknüpfung der Prozessabschnitte untereinander kann im Kontext des Gesamtprogramms interaktiv mit dem Benutzer erfolgen. Für jeden Prozessabschnitt-Klasse muss eine passendes Visualisierungsklasse existieren. Diese sollte über die Ein-und Ausgabeschnittstellen mit der Prozessklasse komunizieren und ein Steuerelement (z.B. ein Frame mit Reglern und Anzeigen) bereitstellen, steuern und Eingaben an die Prozessklasse weitergeben. |
AW: Thread - Synchronize - 2 Forms - Verständnisproblem
Hab das jetzt so gelöst jetzt funktioniert es allerdings lässt sich das fenster nicht mehr verschieben wenn der Thread am zählen ist.
Delphi-Quellcode:
type
ParseThread = class(TThread) private { Private-Deklarationen } Form1: TForm1; i:integer; protected procedure Execute; override; procedure DoSomething; public { Public-Deklarationen } constructor Create(Form1: TForm1); end; var Form1: TForm1; tt: ParseThread; implementation {$R *.dfm} procedure ParseThread.Execute; begin while not Terminated do begin Synchronize(DoSomething); end; end; procedure ParseThread.DoSomething; begin inc(i); form1.Memo1.Lines.Add(inttostr(i)); if i = 5000 then begin i:=0; SuspendThread(tt.Handle); end; end; constructor ParseThread.Create(Form1: TForm1); begin inherited Create(False); Self.Form1 := Form1; end; procedure TForm1.BitBtn1Click(Sender: TObject); begin tt := ParseThread.Create(Self); tt.FreeOnTerminate := true; end; end. |
AW: Thread - Synchronize - 2 Forms - Verständnisproblem
Delphi-Quellcode:
Damit eliminierst du den Vorteil eines Threads und kannst ihn auch gleich weg lassen.
Synchronize(DoSomething);
Hör auf den Rat den du hier im Forum bekommen hast, und arbeite ich in die Grundlagen ein. |
AW: Thread - Synchronize - 2 Forms - Verständnisproblem
Zitat:
Aber es funktioniert, ist zuverlässig und einfach - und sofern der Thread 90% seiner Arbeit außerhalb des Synchronize macht, auch kein Problem! Also ja, das ist sinnlos:
Delphi-Quellcode:
Das hingegen absolut sinnvoll und schön kurz + gut lesbar:
procedure ParseThread.Execute;
begin while not Terminated do begin Synchronize(DoSomething); end; end;
Delphi-Quellcode:
Wobei LongrunningCalculation ruhig länger dauern darf (ist ja entkoppelt vom Hauptthread) und die Ergebnisse in Feldvariablen der Klasse schreibt. Da Synchronize blockiert, sollte Zugriff auf die Feldvariablen sicher sein. (Das ist mMn auch der Grund, weshalb es blockiert: Damit man über private Felder Daten austauschen kann)
procedure ParseThread.Execute;
begin while not Terminated do begin LongrunningCalculation(); Synchronize(ShowProgress); end; end; Da
Delphi-Quellcode:
eben sehr flott ist, ist mMn das Beispiel schlecht gewählt. Eventuell ginge Primzahlen finden besser, da zeitaufwändiger ...?
inc(i)
|
AW: Thread - Synchronize - 2 Forms - Verständnisproblem
Es hat mich nicht ganz losgelassen, daher hier mal ein Beispiel das Primzahlen sucht. Ja, die Berechnung ist absichtlich langsam, wobei ich nicht schätzen kann, wie langsam :stupid: (Und ich hab das ohne IDe hingetippt, vll. sind da noch kleine Fehler drin)
Der Thread ist (bzgl. Abhängigkeiten) entkoppelt von der UI und steltl nur ein Event zur Verfügung. die UI kann (am Besten in einer anderen unit) dann das Event abonnieren und den Fortschritt anzeigen.
Delphi-Quellcode:
type
TPrimeInfoEvent = procedure(Sender: TPrimeFinderThread; number: Integer) of Object; TPrimeFinderThread = class(TThread) private testNumber: Integer; isPrime: Boolean; protected procedure Execute; override; procedure ShowProgress; function IsNumberPrime(number: Integer); fProgressCallback: TPrimeInfoEvent; public { Public-Deklarationen } constructor Create(Form1: TForm1); end; implementation constructor PrimeFinderThread.Create(callback: TPrimeInfoEvent); begin inherited Create(False); Self.fProgressCallback = callback; FreeOnTerminate := True; end; procedure PrimeFinderThread.Execute; begin testNumber = 10000; while not Terminated and testNumber < 1e7 do begin if IsNumberPrime(testNumber) then Synchronize(ShowProgress); testNumber := testNumber+1; end; end; procedure PrimeFinderThread.ShowProgress; begin fProgressCallback(Self, testNumber); end; function PrimeFinderThread.IsNumberPrime(number: Integer): Boolean; var i: Integer; divisorCount: Integer; remainder: Integer; begin divisorCount := 0; for i := 1 to number do begin remainder := number; while remainder >= i do { remainder := number mod i } begin remainder := remainder - i; end if remainder = 0 then inc(divisorCount); end Result := divisorCount = 2; end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:42 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