AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Thread - Synchronize - 2 Forms - Verständnisproblem

Thread - Synchronize - 2 Forms - Verständnisproblem

Offene Frage von "jfheins"
Ein Thema von Pilloker · begonnen am 1. Jul 2009 · letzter Beitrag vom 20. Apr 2020
Antwort Antwort
Seite 3 von 3     123
dustin

Registriert seit: 1. Jun 2009
7 Beiträge
 
#1

Re: Thread - Synchronize - 2 Forms - Verständnisproblem

  Alt 14. Jul 2009, 20:27
Hallo,

mit dem ganzen Threating steige ich nicht so richtig hinter.

Jetzt habe ich gnadenlos drauf losprogrammiert ohne Rücksicht auf Verluste.

Neben dem Hauptprogramm habe ich mir einen Thread erstellt (ShowThread = class(TThread)
mit dem ich meine Ablaufsteuerung realisiert habe.
In der Ablaufsteuerung greift der Thread direkt auf einen Record (array) zu wo er sich Daten für seine Aufgabe holt und seine Ergebnisse auch wieder ablegt.
Die Daten für die VLC Komponenten mache ich über Synchronize denke das ist ok.

Auf die Felder auf die er seine Ergebnisse ablegt, schreibt auch kein anderer Thread Daten rein
also nur ein Ausgabepuffer.

Jetzt benötige ich noch einen Thread (OutputThread) der aus den Ergebnissen des Thread (ShowThread) die eigentlichen Ausgangsdaten erzeugt, muss ich da auf etwas achten (kritischer Abschnitt oder so) wenn die Daten von anderen Threads nur gelesen werden oder kann es zu Konflikten kommen?

MfG Dirk
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.487 Beiträge
 
Delphi 12 Athens
 
#2

Re: Thread - Synchronize - 2 Forms - Verständnisproblem

  Alt 15. Jul 2009, 08:04
Sobald ein Thread in einen bestimmten Speicherbereich schreibt, ist ein "kritischer Abschnitt" erforderlich, wenn andere Threads ebenfalls lesend oder schreibend auf diesen Speicherbereich zugreifen sollen.
  Mit Zitat antworten Zitat
dustin

Registriert seit: 1. Jun 2009
7 Beiträge
 
#3

Re: Thread - Synchronize - 2 Forms - Verständnisproblem

  Alt 22. Jul 2009, 20:01
Hallo an alle,

ich bin wahrscheinlich zu bl.....

Ich steige da nich hinter, habe zwar ein wenig gelesen aber das was ich will ist nirgens nur ansatzweise zu finden.

Habe mir mal erlaub ein Stück Quellcode reinzusetzen.

Delphi-Quellcode:
unit ShowThreadPars;

interface

uses
Windows, Messages, Classes, SysUtils, Forms, Variants, Graphics, Controls,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls, ToolWin, ParFrame;

type
  ShowThread = class(TThread)
  procedure SetData(Value:Byte);
  procedure ParsOut;
  function SetColor(Value:Byte; index:Byte): TColor;

  protected
    procedure Execute; override;
  end;

Var
   tParsindex : Byte; // Rückgabewert
   tTrackbarValue : Byte; // Rückgabewert
   tLabelValue : String; // Rückgabewert
   tShapeColor : Tcolor; // Rückgabewert

   tShapeValue : Byte;
   tDmxAdr : Byte;
   tDMXValue: Byte;
   tFrames : Integer;


   tProgRunOld : array [1..32] of Byte;
   tProgRunTemp : array [1..2,1..32] of Byte;
   tProgStepTemp : Byte = 1 ;

implementation

uses ProLightControlForm;


// -----------------------------------------------------------------------------

procedure ShowThread.Execute;
Var
 I : Byte;
begin
// stopen des thread durch hauptprogramm
  while fThreadParExit do
    begin

-------------------------------------------------------------------------------------
 'PARMAX' ist eine Variabel aus dem Hauptprogramm die sich aber jederzeit ändern kann
 auch wärend der Tread läuft
-------------------------------------------------------------------------------------
// hauptschleife für alle parser
      For i:= 1 to ParMax do
       begin
.
.
.
-------------------------------------------------------------------------------
HIER GREIFE ICH AUF VARIABLE IM HAUPTTREAD ZU UM SIE ZU LESEN BZW. ZU SCHREIBEN
-------------------------------------------------------------------------------

      tDmxAdr := ParCount[i,1]; // dmx adresse des pars hohlen
       if fStandbyActive then
         begin
            Device[tDmxAdr].DMXP := ProgRun[ProgStep,i]; // daten in ausgabe-array zurückschreiben
            tProgRunOld[i] := ProgRun[ProgStep,i]; // hilfsarray für flash funktion...
          end else begin
             Device[tDmxAdr].DMXP := tProgRunOld[i];// daten aktuell halten
          end;
.
.
.
---------------------------------------
HIER SCHREIBEN ICH DIREKT IN DEN RECORD
---------------------------------------

         if Device[tDmxAdr].ParStatus = 1 Then Device[tDmxAdr].DMXP := 255;
         SetData(tDmxAdr); // ausgabedaten berechnen
.
.
.

-----------------------------
AKTUALISIEREN DER VCL OBJEKTE
-----------------------------

         if tProgRunTemp[1,tDmxAdr] <> tProgRunTemp[2,tDmxAdr] then
// Ausgabe visualisierung
            Synchronize(ParsOut);
             tProgRunTemp[2,tDmxAdr]:=tProgRunTemp[1,tDmxAdr];
        sleep(1);
       end;
// end For next
    end;
end;
// -----------------------------------------------------------------------------
// end For next
    end;
end;
// -----------------------------------------------------------------------------

procedure ShowThread.ParsOut;
Begin
ProLightForm.Thread_Parasync(tParsindex, tTrackbarValue,tLabelValue, tShapeColor)
end;
// -----------------------------------------------------------------------------

procedure ShowThread.SetData(Value:Byte);
Var
 dmxValueStr : String;
  begin
      tShapeValue := Device[tDmxAdr].ParColorSet; // Colorindex holen
      tDMXValue := Device[tDmxAdr].ParDmxOut; // Programmwert holen
      tProgRunTemp[1,tDmxAdr]:=tDMXValue;
                                                      // nach speedfader
.
.
.
.
Es funktioniert zwar alles störungsfrei aber ich denke das es nicht richtig ist, wäre sonst zu
einfach.

Kann mir da mal jemand helfen, wie ich einen sauberen Zugriff auf Variable im Haupttread hinbekomme da die sich ständig ändernden Daten und der Tread darauf reagieren soll.


MfG Dirk
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.487 Beiträge
 
Delphi 12 Athens
 
#4

Re: Thread - Synchronize - 2 Forms - Verständnisproblem

  Alt 23. Jul 2009, 10:08
Delphi-Quellcode:
Var
   tParsindex : Byte; // Rückgabewert
   tTrackbarValue : Byte; // Rückgabewert
   tLabelValue : String; // Rückgabewert
   tShapeColor : Tcolor; // Rückgabewert

   tShapeValue : Byte;
   tDmxAdr : Byte;
   tDMXValue: Byte;
   tFrames : Integer;


   tProgRunOld : array [1..32] of Byte;
   tProgRunTemp : array [1..2,1..32] of Byte;
   tProgStepTemp : Byte = 1 ;

implementation
Diese ganzen globalen Variablen gehn überhaupt nicht. Eine Variable sollte immer jemanden gehören.
In diesem Fall entweder einem Formular oder dem Thread und jeweils dort in den private oder protected-Abschnitt deklariert. Andere Klassen können grundsätzlich nur über property auf diese Variablen zugreifen.
-----------------------------------------------------------------------------

Delphi-Quellcode:
uses ProLightControlForm;
{...}
Synchronize(ParsOut);
{...}
procedure ShowThread.ParsOut;
Begin
ProLightForm.Thread_Parasync(tParsindex, tTrackbarValue,tLabelValue, tShapeColor)
end;
Das gehört so nicht in eine Unit, die sich um die Funktionalität kümmert (Trennung von Funktionaliät und Oberfläche).
Man kann zwei Fälle unterscheiden:
1. das Ereignis muss sofort bearbeitet und der Thread in der Zwischenzeit anhalten
2. das Ereignis kann bei nächster Gelegenheit verarbeitet werden, der Thread kann weiter arbeiten

Fall 1.:
In diesem Fall ist Synchronize() erforderlich.
Die Methode sollte aber nicht direkt, sondern über einen Methodenzeiger(oder Interface) erfolgen.
Delphi-Quellcode:
TParasyncMethode = procedure(Sender: TObject {optional weitere Parameter}) of object;

ShowThread = class(TThread)
{...}
  private
    FOnParasync: TParasyncMethode;
    procedure SetOnPararasync(AValue: TParasyncMethode);
    function GetOnPararasync: TParasyncMethode;
  public
    property OnParasync: TParasyncMethode read GetOnPararasync write SetOnPararasync;
{...}

procedure ShowThread.ParsOut;
var
  lParasync: TParasyncMethode;
Begin
  lParasync := GetOnPararasync;
  if Assigned(lParasync) then
    lParasync(Self {optional weitere Parameter});
end;
Fall 2.:
Synchronize() ist nicht erforderlich.
Der Hauptthread wird asynchron mit Hilfe von Nachrichten informiert.
Man kann ein eigenes threadsicheres Nachrichtensystem implementieren oder man nutzt das von Windows.
Delphi-Quellcode:
const
  WM_Parasync = WM_User + XXX;

ShowThread = class(TThread)
{...}
  private
    FParasyncWnd: THandle;
    procedure SetPararasyncWnd(AValue: THandle);
    function GetPararasyncWnd: THandle;
  public
    property ParasyncWnd: THandleread GetPararasyncWnr write SetPararasyncWnd;
{...}

procedure ShowThread.ParsOut;
var
  lParasyncWnd: THandle;
Begin
  lParasyncWnd := GetParasyncWnd;
  if Assigned(lParasyncWnd) then
    PostMessage(lParasyncWnd, WM_Parasync, Integer(Pointer(Self)), 0 {Optional weiterer Parameter});
end;
-----------------------------------------------------------------------------

Threadsicherer Zugriff auf interne Variabeln eines Objekts über Getter und Setter:
Delphi-Quellcode:
private
  FSection: TCriticelSection; {im Konstruktor erzeigen, im Destrucor freigeben, in der Regel wird nur eine je Objekt benötigt}
{...}

procedure ShowThread.SetPararasyncWnd(AValue: THandle);
begin
  FSection.Acquire;
  try
    FPararasyncWnd := AValue;
  finally
    FSection.Release;
  end;
end;

function ShowThread.GetPararasyncWnd: THandle;
begin
  FSection.Acquire;
  try
    Result := FPararasyncWnd;
  finally
    FSection.Release;
  end;
end;
Auf die interne Variable FPararasyncWnd darf in diesem Fall nirgends sonst zugegriffen werden,
einzige Ausnahme in einem genauso mit FSection abgesicherten Abschnitt.
Der selbe Mechanismus müsste auch in alle anderen Klassen eingebaut werden, auf dessen Property der Thread zugreifen soll.
Das würde ich aber vermeiden, neue Daten sollten immer vom Hauptthread and den Subtrhead übergeben oder von dort abgeholt werden.

Der letzte Satz sollte eigentlich deine Frage beantworten, übergib geänderte Daten an eine so absicherte Methode.
Der Thread erstellt sich eine Kopie davon und arbeitet mit dieser.

Schreibfehler wurden eingefügt, um die Aufmerksamkeit des Lesers zu erhöhen.
  Mit Zitat antworten Zitat
dustin

Registriert seit: 1. Jun 2009
7 Beiträge
 
#5

Re: Thread - Synchronize - 2 Forms - Verständnisproblem

  Alt 23. Jul 2009, 17:03
Hallo,

vielen Dank erstmal, ich kau das erst mal durch und muss es verdauen.

Mfg Dirk
  Mit Zitat antworten Zitat
dustin

Registriert seit: 1. Jun 2009
7 Beiträge
 
#6

Re: Thread - Synchronize - 2 Forms - Verständnisproblem

  Alt 27. Jul 2009, 19:49
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.
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.487 Beiträge
 
Delphi 12 Athens
 
#7

Re: Thread - Synchronize - 2 Forms - Verständnisproblem

  Alt 28. Jul 2009, 10:44
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.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 09:35 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