Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Zugriff synchronisieren (https://www.delphipraxis.net/77053-zugriff-synchronisieren.html)

hanspeter 14. Sep 2006 07:48


Zugriff synchronisieren
 
Hallo,
ich plage mich mit folgenden Problem.

In einen Ringpuffer werden Daten zyklisch geschrieben und gelesen.
Das funktioniert auch wie gewünscht.
Den Lese- und den Schreibvorgang habe ich in einer kritischen Sektion eingeschlossen.

Also

Delphi-Quellcode:
FLock       : TCriticalSection;


 FLock.Acquire;
 FLock.Enter;
schreibe Daten in den Buffer
FLock.Release;
Um das Teil zu stressen schreibe ich über einen Timer zyklisch Daten und Lese diese wieder.
Schreibe ich jetzt zusätzlich Daten über einen Schalter in den Buffer, kommt eine Speicherschutzverletzung.
Das heist, dass der als kritische Sektion gekapselte Vorgang offensichtlich nicht abgeschlossen ist,
und der über Schalter ausgelöste asynchrone Schreibzugriff in den gerade laufenden fuscht.

Hat wer eine Idee, wie ich den Schreibvorgang in den Buffer absichern kann,
ohne das eine Unterbrechung möglich ist?

Mit Gruß Peter

Harry M. 14. Sep 2006 08:24

Re: Zugriff synchronisieren
 
Kann es sein das jede Klasse ihre eigene TCritical hat? Wo deklariertst Du diese?
Ferner würde ich auch
Delphi-Quellcode:
 Flock.Enter
und
Delphi-Quellcode:
 Flock.Leave
nutzen ;-)

hanspeter 14. Sep 2006 08:37

Re: Zugriff synchronisieren
 
Zitat:

Zitat von Harry M.
Kann es sein das jede Klasse ihre eigene TCritical hat? Wo deklariertst Du diese?
Ferner würde ich auch
Delphi-Quellcode:
 Flock.Enter
und
Delphi-Quellcode:
 Flock.Leave
nutzen ;-)

Ich habe eine Klasse TRingbuffer.
In dieser ist Flock : TCriticalSection declariert.

Vor Aufruf von PutBlock (einen Datenblock in den Ringpuffer schreiben) wird als erstes ein
FLock.Enter ausgeführt.

Vor dem Verlassen der Funktion ein FLock.Release.

Warum ist Enter und Leave besser ?

Danke.
Mit Gruß
Peter

Edit: Rechtschreibfehler

Der_Unwissende 14. Sep 2006 08:42

Re: Zugriff synchronisieren
 
Hi,
// WEGEN ROTEM KASTEN GESTRICHEN/GELÖSCHT
...

Ansonsten kannst du ja auch schauen, ob die Sektion betreten wird. Schreib dir einfach ein einfachen Test, der in der criticalSection eine Endlosschleife enthält oder einfach die Section nicht freigibt. Dann lässt du noch per ShowMessage einen Hinweis aufpopen, wenn jmd. diese Sektion betritt. Wenn hier ein solcher Hinweis kommt, wenn du die Sektion über einen Schalter betreten möchtest, wärend die Section eigentlich gesperrt ist, dann hast du etwas geschafft was eigentlich nicht möglich sein sollte.

Gruß Der Unwissende

hoika 14. Sep 2006 09:05

Re: Zugriff synchronisieren
 
Hallo,

das Aquire / Enter muss nicht zweimal aufgerufen werden (siehe Hilfe)

Delphi-Quellcode:
LockXY.Acquire; { Andere Threads blockieren }
try
  Y := sin(X);
finally
  LockXY.Release;
end;
Was mich hier stutzig macht, ist das "Andere Threads blockieren".
Wenn du über einen Timer schreibst, bist du ja im gleichen Thread!

Falls ich das richtig verstehe, nützt also eine critical section nichts,
ich würde es mal mit nem Mutex probieren.


Heiko

Harry M. 14. Sep 2006 09:06

Re: Zugriff synchronisieren
 
Wie oft wird die Klasse TRingBuffer erzeugt?? Mehr als 1x?

Warum Du
Delphi-Quellcode:
 Flock.Leave
nutzen sollst. Hm.... gute Frage!? Ich arbeite mit Leave. Habe keine Probleme beim Synconisieren. Klammerst Du auch mit Synchronize aus?

Die Delphi-Hilfe verrät folgendes:
Delphi-Quellcode:
Mit Acquire wird die Anbindung aller anderen Threads an diesen kritischen Abschnitt so lange blockiert, bis eine der Methoden Release oder Leave aufgerufen wird. Acquire hat denselben Effekt wie die Methode Enter.
Dein Code:
Delphi-Quellcode:
FLock.Acquire;
FLock.Enter;
....
Meiner Meinung nach betrittst Du die Sections quasi 2x. Kann aber auch sein das ich falsch liege. :roll:

@hoika: Da war wohl einer schneller :mrgreen:

hanspeter 14. Sep 2006 09:11

Re: Zugriff synchronisieren
 
Zitat:

Delphi-Quellcode:
Mit Acquire wird die Anbindung aller anderen Threads an diesen kritischen Abschnitt so lange blockiert, bis eine der Methoden Release oder Leave aufgerufen wird. Acquire hat denselben Effekt wie die Methode Enter.

Das Enter war nur testweise reingekommen.
Aber der Hinweis oben sollte richtig sein.
die klasse gibt es nur einmal und da ich diese im gleichen Kontext (Thread) verwende, kann die Criticalsection ja
nicht funktionieren.
Ich rufe die Schreibroutine einmal von einem Timer auf und dann zusätzlich über einen Schalter.

Mutex habe ich noch nicht verwendet, werde es aber sofort mal probieren.



Gruß
Peter


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:30 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