AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Thread CriticalSection bzw TMultiReadExclusiveWriteSynchronizer pro Property
Thema durchsuchen
Ansicht
Themen-Optionen

Thread CriticalSection bzw TMultiReadExclusiveWriteSynchronizer pro Property

Ein Thema von norwegen60 · begonnen am 7. Nov 2019 · letzter Beitrag vom 18. Nov 2019
Antwort Antwort
Seite 2 von 2     12   
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
961 Beiträge
 
Delphi 6 Professional
 
#11

AW: Thread CriticalSection bzw TMultiReadExclusiveWriteSynchronizer pro Property

  Alt 17. Nov 2019, 06:20
Hmm..


Delphi-Quellcode:

procedure TthrTest.Execute;
//******************************************************************************************************************************************
begin
  inherited;

  while not Terminated do
  begin
    FSection.Acquire; // Zugriff auf FListe schützen
    try
      if FListe.Count > 0 then
      begin
        Wert := FListe[0]; // ---->> Zugriff auf die Property 'Wert' und somit auf den Setter 'SetWert'
        FListe.Delete(0);
      end;
    finally
      FSection.Release; // Zugriff auf FListe wieder freigeben
    end;
    TThread.Sleep(300);
  end;
end;

procedure TthrTest.SetWert(const Value: String);
//******************************************************************************************************************************************
var
  bChanged: Boolean;

begin
  FSection.Acquire; // Zugriff auf FWert schützen
  try
    bChanged := (FWert <> Value);
    if bChanged then
      FWert := Value;
  finally
    FSection.Release; // Zugriff auf FWert wieder freigeben
  end;

  // Nicht innerhalb der CriticalSection da Main sonst blockieren könnte
  if bChanged then
    Synchronize(SyncEventWert);
end;

Der DeadLock kommt hier deshalb, weil Du innerhalb des Locks im Execute auf den Setter von Wert zugreifst, welcher selber wieder ein Lock machen will...

Dein Synchronize sollte auch nicht im Setter, sondern im Execute gemacht werden..

Delphi-Quellcode:

procedure TthrTest.Execute;
var
  tmpDataToSend : String;
begin
  inherited;

  FWert := '';

  while not Terminated do
  begin
    FSection.Acquire; // Zugriff auf FListe schützen
    try
      if FListe.Count > 0 then
      begin
        FWert := FListe[0];
        FListe.Delete(0);
      end;
    finally
      FSection.Release; // Zugriff auf FListe wieder freigeben
    end;


    // Nicht innerhalb der CriticalSection da Main sonst blockieren könnte
    if FWert <> 'then begin
      Synchronize(SyncEventWert);
      FWert := '';
    end;

    TThread.Sleep(1);
  end;
end;

Deine Property Wert mit seinem Setter ist somit Überflüssig,ja sogar falsch, da deine Liste über 'SendToListe' gefüllt wird und auf FWert nur innerhalb von Execute zugegriffen werden sollte, da dieser nur für Synchronize benötigt wird.

Für den Sleep genügt auch ein Wert von einer MS...
(Ja ich Verwende Delphi 6 Pro und will NICHT wechseln!)
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
504 Beiträge
 
Delphi 12 Athens
 
#12

AW: Thread CriticalSection bzw TMultiReadExclusiveWriteSynchronizer pro Property

  Alt 17. Nov 2019, 13:44
Es ist immer das selbe Problem. Wenn man seinen ganzen Sourcecode ausgeben würde, würde der Code zu kompliziert. Reduziert man ihn auf das (vermeintlich) Wesentliche, sieht der Beispielcode kompliziert aus.

In meinem Fall wird Wert in Wirklichkeit von der RS232 zurück geliefert, über AsyncPro.ComPortTriggerAvail erfasst und dort auch Wert gesetzt. D.h. Exceute bekommt davon gar nichts mit. Deshalb das Synchronize im Setter. Mit deiner Änderung würde Execute nichts mitbekommen wenn ich den Wert über den Button [Write into Wert] vom Main her ändere. Das würde dein Execute nicht erkennen und somit auch nichts an den Main zurück liefern. (In dem Fall simuliert der Button [Write into Wert] den PortTrigger.)

Mit dem Doppel-Lock in meinem Execute-Beispiel hast du recht. Tritt aus vorigen Gründen so im Echtcode aber nicht auf.
Das seltsame: Trotz des Doppellock im Exceute läuft mein ZIP-Beispiel ohne Probleme. Nur der Echtcode nicht. Ich bin dabei den Beispielcode mehr und mehr an meine Realcode ranzubringen.

Den Sleep habe ich so lang gemacht um simulieren zu können, dass sich die Liste auch mal schneller füllt als sie abgearbeitet wird und trotzdem kein Befehl verliert.

Darf Synchronize wirklich nur in Exceute aufgerufen werden
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
961 Beiträge
 
Delphi 6 Professional
 
#13

AW: Thread CriticalSection bzw TMultiReadExclusiveWriteSynchronizer pro Property

  Alt 17. Nov 2019, 20:43
Hmm..

Wenn 'Wert' eh nur direkt gesetzt wird, dann kannst Du auch deinen kompletten Thread wegschmeißen!

Nur wenn dein AsyncPro.ComPortTriggerAvail das 'SendToListe' verwendet, kann die Liste überhaupt funktionieren..
Und nur dann könntest Du den Thread brauchen...
(Ja ich Verwende Delphi 6 Pro und will NICHT wechseln!)
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
504 Beiträge
 
Delphi 12 Athens
 
#14

AW: Thread CriticalSection bzw TMultiReadExclusiveWriteSynchronizer pro Property

  Alt 18. Nov 2019, 00:16
Noch mal: In meinem Beispiel wollte ich die Situation simulieren, dass zwei Threads auf ein und denselben Wert zugreifen. Deshalb wird dieser Wert über Exceute aus der Liste gefüllt als auch über einen Button-Klick aus dem Main-Thread. Dies nur um zu testen, ob ich Konflikte erzeugen kann

Im realen Code sendet der Main Befehle in eine Liste des Thread. Diese Befehle werden in Execute aus der Liste an den ComPort geschickt. Ein neuer Befehl wird aber erst geschickt, wenn der vorherige geantwortet hat. Deshalb das Puffern in der Liste.
Irgendwann antwortet das angeschlossene Gerät und die Antwort wird über das Event ComPortTriggerAvailable so lange gesammelt bis sie komplette ist. Dann wird sie in Wert geschrieben und damit über den Setter an den Main geschickt. Danach kann Executen den nächsten Befehl aus der Lsite auslesen und an den ComPort schicken. Zwischenzeitlich kann der Main aber schon weitere Befehle an die Liste geschickt werden.
Auch wenn der Wert über Synchronize an den Main übergeben wurde, soll es möglich sein, diesen Wert auch manuell abzufrage ohne dass es kracht.

Geändert von norwegen60 (18. Nov 2019 um 00:20 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   

 

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 03:48 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