Announcement

Collapse
No announcement yet.

Synchronize: Aufruf von Funktionen mit Übergabeparametern

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Synchronize: Aufruf von Funktionen mit Übergabeparametern

    Hallo,

    ich suche eine Möglichkeit, mit der Funktion synchronize eine Funktion mit Übergabeparametern aufzurufen. Ich habe einen Thread und möchte nun bspweise vom Objekt 'Gauge' die Eigenschaft 'Progress' ansteuern.

    Mit synchronize geht das schon, wenn man mit globaler Variable arbeitet. Aber ist noch ein anderer relativ einfacher Weg möglich [Funktion mit Übergabeparameter] ?

    MfG
    Sebastian Hagedorn

  • #2
    Normalerweise erstellt man ja eine neue von TThread abgeleitete Klasse, und somit Felder in diesem Object die die Parameter darstellen.

    <pre>
    type
    TMyThread = class(TThread)
    private
    FProgress: Integer;
    FProgressBar: TProgressBar;
    procedure DoProgress;
    protected
    procedure Execute; override;
    public
    constructor Create(ProgressBar: TProgressBar);
    end;<br>

    procedure TMyThread.DoProgress;
    begin
    FProgressBar.Position := FProgress;
    end;<br>

    procedure TMyThread.Execute;
    begin
    while not Terminated do
    begin
    Sleep(250);
    FProgress := FProgress +1;
    Synchronize(DoProgress);
    end;
    end;<br>

    constructor TMyThread.Create(ProgressBar: TProgressBar);
    begin
    inherited Create(False);
    FProgressBar := ProgressBar;
    end;<br>

    </pre>

    gruß Hage

    Comment


    • #3
      Hallo,

      wenn ich jetzt anstelle von einem Progressbar ein Meminifile (aus dem Hauptformular) verwende und aus den Threads (mehrere) nur lesend zu greife muss ich dann auch mit der Methode Synchronize arbeiten?

      Und wie sperre ich das MemIniFile wenn ich im Hauptformular neue Datenhinzufüge mit WriteString zum Beispiel. Oder muss ich es überhaupt nicht sperren?

      <pre>
      type
      TMyThread = class(TThread)
      private
      FString: String;
      FMemIniFile: TMemIniFile;
      procedure DoRead;
      // ....
      public
      constructor Create(AMemIniFile: TMemIniFile);
      end;
      <br>
      procedure TMyThread.DoRead();
      begin
      FString := FMemIni.ReadString('Group','Value','Fehler');
      end;
      </pre>
      <p>
      <i>mgf <br>
      stephan</i&gt

      Comment


      • #4
        Dieses MemIniFile könnte direkt im Thread erzeugt werden, d.h. jeder Thread nutzt sein eigenes. Dies sollte der generelle Weg sein, also jeder Thread läuft wie eine eigene Anwendung mit eigenen Daten, BDE Session usw. In solchen Konstellationen bekommt man die wenigsten Probleme bzw. nur solche die man mit mehreren App's gleichzeitig auch hätte.<br>

        Sollten alle Thread auf das gleiche MemIniFile zugreifen so sollte entweder der Lese/Schreibzugriff über Synchronize() an einen Hauptthread delegiert werden, oder aber der Zugriff per Critical Section geblockt werden. Dazu wird eine globale RTL-CS erzeugt, z.B. in der Unit initialization/finalization und bei JEDEM Zugriff dann mit dieser CS geblockt. Allerdings MÜSSEN dann alle Zugriffe geblockt werden, es kann also nicht sein das es Zugriffe gibt die an der CS vorbeigehen. In Deinem Falle dürfte das der beste Weg sein, da nicht anzunehmen ist das es viele gleichzeitige wiederholte Zugriffe auf das MemIniFile gibt. Eine oft benutzte und veränderte Resource würde im Falle des CS-Blockings die Gesamtlaufzeit der Anwendung reduzieren oder sogar blockieren.<br>
        Ich persönlich versuche als erstes die Anzahl gemeinsammer Resourcen zu reduzieren, den Rest mit CS zu blocken und nur in speziellen Fällen über Synchronize() zu arbeiten. Ich mag die Borland Synchronize() Methodik nicht besonders und wie in D6-Kylix gezeigt gibts genau da einige Problemchen's. Eine Alternative, die ich gerne nutze, ist falls die Threads im Rahmen eines TForms benutzt werden eine benutzerdefinierte Message an diese Form abzusetzen (SendMessage()).
        Im Grunde IST das identisch mit Synchronize() nur nicht so anfällig meiner Meinung nach.

        Gruß Hage

        Comment


        • #5
          Hi,

          ich habe mal das Forum durchforstet und bin dabei auf <i>TMultiReadExclusiveWriteSynchronizer</i> gestossen. Sind die sinnvoll bei einem MeminiFile, das in mehreren Threads ausgelesen wird, einzusetzen?

          Gibt es für die Klasse <i>TMultiReadExclusiveWriteSynchronizer</i> Grenzen, wo sollte ich sie nicht einsetzen? Wahrscheinlich <b>nicht</b> mit einer Oberfläche der Hauptanwendung zusammen?

          <i>
          mfg
          stephan
          </i&gt

          Comment


          • #6
            Hallo Stephan,<br>
            evt hilft Dir ja der folgende Link weiter<br>
            http://community.borland.com/article/0,1410,28258,00.html<br&gt

            Comment


            • #7
              eigentlich funktioneren sie gut, solange man bei D5 bleibt. Unter D6 gibts mit dem Locking,Synchronize usw. usw. echte Probleme.
              Im Gegensatz zu Critical Sections, also Voll Sperrung, versucht der MREWS das Schreiben zu blocken so daß nur einer Schreiben kann und das Lesen readonly für alle Threads zu erlauben WENN nicht gerade ein Thread schreibt.<br>
              Für die Anwendung ändert sich im Vergleich zu RTL-CS's nichts, d.h. JEDER Zugriff ob lesend oder schreibend muß mit der gleichen RTL-CS's geblockt oder mit dem gleichen MREWS Object geblockt werden.
              Im grunde ist es doch so: in jedem Multitasking System kann man eigentlich OHNE jedweigen Schutzmaßnahmen in parallel readonly auf Daten Zugreifen, dies ist legal. Problematisch ist eigentlich nur ein Lesezugriff wenn zum gleichen Zeitpunkt ein anderer Task/CPU die Daten schreibt. Im Windows System wird garantiert das auch Schreibvorgänge auf atomic datentypen threadsafe sind. D.h. einen Integer per atomic Assemblerbefehl gelesen oder geschrieben, soll angeblich Threadsafe sein.
              z.b.

              <pre>

              var
              I: Integer;<br>

              asm
              MOV EAX,I // lese I in register EAX des akt. Threads
              MOV I,EAX // schreibe I aus register EAX
              end;

              </pre>

              Gruß Hage

              Comment

              Working...
              X