Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Welches Form des wechselseitigen Auschlusses(Semaphore)?! (https://www.delphipraxis.net/109152-welches-form-des-wechselseitigen-auschlusses-semaphore.html)

DelphiManiac 25. Feb 2008 12:23


Welches Form des wechselseitigen Auschlusses(Semaphore)?!
 
Hallo,

ich habe eine Methode meines Objekts, die intern Application.ProcessMessages aufruft,

ich will aber nicht, dass in die Methode nocheinmal "reingesprungen" wird, solange sie noch aktiv ist.
Meine Frage ist nun, welche Synchronisationsmethoden (viell. eine Semaphore?) ist da sinnvoll?
Oder kann man hier eine TCriticalsection nutzen?

so sieht meine Methode grob aus:

Delphi-Quellcode:
begin
  //--------> Hier SyncEintritt
  MachEtwasHier;
  MachEtwasDort;
  while (...) do
  begin
    MachHierWasSpektakulaeres;
    Application.ProcessMessages;
  end;
  //--------> Hier SyncAustritt
end;
Danke schonmal für eure Anregungen
P.S.: Habe das Script von Luckie habe ich gelesen

sirius 25. Feb 2008 12:29

Re: Welches Form des wechselseitigen Auschlusses(Semaphore)?
 
CriticalSection geht nicht, da du in eine CritcalSection mehrmals hineinlaufen kannst, solange du im gleichen Thread bist. Und das ist hier ja der Fall. Semaphore oder Event würde gehen, aber:
Application.ProcessMessages zu verwenden ist (fast) immer ein falscher Konzeptansatz. Und wenn du schon über Synchronistaionsobjekte sprichst, warum nimmst du nicht gleich einen Thread. Meistens läßt sich ja mit einem Thread das schlechte ineinanderwurschteln von Application.ProcessMessages vermeiden.

Lies dir mal zu Application.ProcessMessages das hier durch:
2. Absatz!
du bist dir ja der Problematik schon bewusst. Versuch sie besser gleich komplett zu umgehen.

SirThornberry 25. Feb 2008 12:31

Re: Welches Form des wechselseitigen Auschlusses(Semaphore)?
 
eine Semaphore würde auch nur gehen wenn diese nicht blockiert. Da hier kein Zugriff durch mehrere Threads stattfindet sondern es immer wieder der gleiche Thread ist kann man es einfach über eine Variable absichern.

DelphiManiac 25. Feb 2008 14:22

Re: Welches Form des wechselseitigen Auschlusses(Semaphore)?
 
@sirius:

Zitat:

Application.ProcessMessages zu verwenden ist (fast) immer ein falscher Konzeptansatz. Und wenn du schon über Synchronistaionsobjekte sprichst, warum nimmst du nicht gleich einen Thread. Meistens läßt sich ja mit einem Thread das schlechte ineinanderwurschteln von Application.ProcessMessages vermeiden.
Da hast du vollkommen Recht, das Design an der Stelle ist nicht sauber, genau da liegt das Problem. Ich doktor jetzt an
den Symptomen rum, müsste mir aber die Auslöser dafür vornehmen.

Das Problem was ich habe ist folgendes:

Ich habe eine Kommunikation zwischen einem Gerät und meiner PC-Soft. Es ist eine Frage Antwort Spielchen:

Frage: Gib mir Daten auf Adress 0x1000
...
Delphi-Quellcode:
// Hier liegt mein Problem, da ich aktiv auf die Antwort warte (warten muss);
// Ich warte auf 6 Bytes (wenn diese in einer Zeitpanne nicht da sind frage ich nochmals nach (3-mal)
// dann muss ich auf einen Timeout detektieren
...

Antwort: Hier die Daten

Und das ist alles in einem Funktionsaufruf gekapselt...

alzaimar 25. Feb 2008 14:35

Re: Welches Form des wechselseitigen Auschlusses(Semaphore)?
 
Das läuft in einem Thread ab... Der Thread heißt 'TAcquireDataThread'. Ihm übergibst du den Port (die 'Adresse') und der macht das dann für dich, also antriggern, warten, Daten lesen (max 3x) etc... Über das OnTerminate-Event teilt er dir mit, das er fertig ist (fehlerfrei oder auch nicht). Das blockiert deine Anwendung nicht und Du kannst problemlos mehrere davon abfeuern. Wenn immer nur ein Leser an einem bestimmten Port lauschen darf, dann erzeugst/öffnest du beim Thread-Beginn eine Semaphore mit Namen 'Port<Portnummer>'. So ist sichergestellt, das immer nur ein Thread pro Port aktiv ist...

Alternativ kannst du den Thread auch fehlerbedingt terminieren lassen, wenn es die Sempahore schon gibt.

DelphiManiac 25. Feb 2008 14:48

Re: Welches Form des wechselseitigen Auschlusses(Semaphore)?
 
Bisher habe ich meine Funktionen immer so gehabt:

function HoleStatus(Status:TStatus) : Integer;

Diese habe ich dann aufgerufen und den Status in der GUI angezeigt,
als direkten Rückgabwert habe ich dann ausgewertet, ob die Funktion erfolgreich ausgeführt wurde.

Angenommen ich mache das jetzt über einen Thread, dann weiss ich ja nie genau, wann er fertig ist, oder?

Denn wenn ich Schreizugriffe auf mein Gerät habe, dann muss ich nach Aufruf defintiv wissen, dass der Schreibzugriff,
erfolgreich war.

@alzaimar:

Den 'TAcquireDataThread' muss ich mir selbst erstellen, richtig?! Oder gibt es soetwas ähnliches schon?

Gruß und Danke!

DelphiManiac 25. Feb 2008 14:53

Re: Welches Form des wechselseitigen Auschlusses(Semaphore)?
 
@alzaimar:

Kannst du mir da evtl. mit ein bisschen Quellcode / Pseudocode auf die Sprünge helfen, da
ich dort nicht so richtig weiterkomme.

Wenn du mir mit dem Ansatz hilfst, wäre echt super!

Danke

shmia 25. Feb 2008 16:37

Re: Welches Form des wechselseitigen Auschlusses(Semaphore)?
 
Ich denke, dass du nur deine Benutzeroberfläche verriegeln musst!!
(Tip: Actions verwenden)
Damit wird verhindert, dass eine Message in Application.ProcessMessages verarbeitet wird und du erneut in deiner Prozedur landest.
Delphi-Quellcode:
begin
  BtnStart.Enabled := False; // <===
  try
    MachEtwasHier;
    MachEtwasDort;
    while (...) do
    begin
      MachHierWasSpektakulaeres;
      Application.ProcessMessages;
    end;
  finally
    BtnStart.Enabled := True;  // <===
  end;
end;
Nachtrag:
wenn das oben eine Methode deiner eigenen Klasse ist, dann wäre Folgendes empfehlenswert:
Delphi-Quellcode:
begin
  // BtnStart.Enabled := False;   // wird ins Formular verlagert
    MachEtwasHier;
    MachEtwasDort;
    while (...) do
    begin
      MachHierWasSpektakulaeres;
      // Eventhandler aufrufen, falls vorhanden
      if Assigned(FOnProgress) then
        FOnProgress(self);  // <===
    end;
  //  BtnStart.Enabled := True;  // wird ins Formular verlagert
end;
Mit dieser Änderung kannst du von Aussen vorgeben, was passieren soll, während die Methode arbeitet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:16 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz