Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   1 Datei und 2 Prozesse ... (https://www.delphipraxis.net/130535-1-datei-und-2-prozesse.html)

moelski 10. Mär 2009 10:14

Re: 1 Datei und 2 Prozesse ...
 
Jo das stimmt.
Ich muss auch gestehen das ich mit dem Konstrukt noch nicht ganz warm geworden bin ...

Aber ich werde das jetzt erstmal so weiter testen. Das Problem an der Sache ... Die Tests sind eher müssig und langwirig ... :|

mkinzler 10. Mär 2009 10:15

Re: 1 Datei und 2 Prozesse ...
 
Trotdem wäre es m.E. besser serverseitig nur die Werte wegzuschreiben ( u.U in Ringpuffer) und das Bild nur bei Bedarf zu erzeugen.

moelski 10. Mär 2009 10:21

Re: 1 Datei und 2 Prozesse ...
 
Moin !

Zitat:

und das Bild nur bei Bedarf zu erzeugen
Das würde bedeuten das ich aber alle x Sekunden eine komplett neue Grafik erzeugen muss und die Werte eintrage. Das kostet imens Zeit. Wir haben Geräte die senden alle 62,5 Millisekunden. Da kommt man dann schnell in Nöte was die Berechnung angeht.
Ok man könnte die Grafik dann in einem Thread erzeugen lassen. Aber dann steigt der Aufwand für diese Grafik doch enorm.

mkinzler 10. Mär 2009 10:26

Re: 1 Datei und 2 Prozesse ...
 
Deshalb ja bei Bedarf. Die Werte werden nur gespeichert und bei Anforderung durch Browser erzeugt.

moelski 11. Sep 2009 05:12

Re: 1 Datei und 2 Prozesse ...
 
Moin !

Ich muss diesen Fred nochmal aufgreifen. Irgendwie bin ich mit der jetzigen Lösung noch nicht im Reinen.
Delphi-Quellcode:
while FileInUse(LPathname) do Application.ProcessMessages;
Sowas widerstrebt mir irgendwie genauso wie Sleep Aufrufe.

Habe jetzt folgende Idee ...

Generell gibt es ja 2 Prozesse die vollkommen asynchron zueinander laufen:
1) Speichern der Webseite
Das speichern erfolgt in einen Temp Ordner. Aufgerufen wird das Speichern der Webseite in unserem Programmlauf. Und zwar dann wenn die Grafik definitiv komplett gezeichnet ist. Das klappt aber eh ...
Gespeichert wird nur (!) SaveDone = False. SaveDone = Boolwert - zeigt das die Webseite neu im Temp abgespeichert wurde und das Speichern abgeschlossen ist. Nach dem Speichern der Seiteninfos SaveDone = True setzen.
Mehr passiert hier nicht - darf auch nicht um den normalen Programmablauf nicht unnötig zu stören.

2) Laden der Webseite aus dem Browser
Jetzt kommt der heikele Part. Denn das Laden der Webseite kann ja z.B. theoretisch von 100 Browsern im Sekundentakt erfolgen. Bei jedem Lesen wird das Event HTTPServer_CommandGet ausgelöst.
Ich klammere deshalb das ganze Lesen mit dem Inkementieren und Dekrementieren eines Counter - nennen wir ihn mal Z.

Also sowas:
Delphi-Quellcode:
INC(Z);
  //.... HTTPServer_CommandGet Code
DEC(Z);
Daraus kann man dann folgende Schlüsse ziehen:
- ist der Counter = 1 dann ist das CommandGet aktuell nur 1x am laufen.
- ist der Counter > 1 dann sind gerade mehrere Leseoperationen am Webserver aktiv.

Wenn der Counter = 1 ist UND SaveDone = True dann wird das Lesen der Webseite geblockt.
Jetzt kopiere ich den Kram vom Temp Ordner ins Webserververzeichnis.
Temp Verzeichnis löschen.
Block aufheben.
SaveDone = False

In Code sähe das dann in etwa so aus:
Delphi-Quellcode:
INC(Z);
  if (Z = 1) AND (SaveDone = True) Then begin
    BlockReading := True;
    // ... COPY Temp to Webfolder
    // ... CLEAR Temp folder
    BlockReading := False;
    SaveDone    := False
  End;
  //.... HTTPServer_CommandGet Code
DEC(Z);
Könnte mir vorstellen das es so ganz gut funktioniert. Genaugenommen ist es zwar immer noch nicht 100%ig, denn wenn genau zwischen "if (Z = 1) AND (SaveDone = True) Then " und "BlockReading := True;" eine neue Leseanforderung kommt, denn könnte es wieder zu Problemen kommen. Aber da unser Webserver dafür eingesetzt wird, eine Chart Grafik darzustellen und wir einen Refresh von 20 Sekunden haben, sollte das verschmerzbar sein.

Evtl. könnte man das auch noch etwas abfangen wenn man nach dem INC(Z) erst ein
Delphi-Quellcode:
BlockReading := (Z = 1) AND (SaveDone = True);
aufrufen würde.

Jedenfalls wäre das eine Lösung die ohne grossartige Sleeps oder sonstige Wartezyklen auskäme.

Oder habe ich was gravierendes übersehen !?

Angel4585 11. Sep 2009 07:00

Re: 1 Datei und 2 Prozesse ...
 
Wie machst du das mit der Erzeugung der Grafik-Datei eigentlich genau?

Also angenommen du hast die Datei grafik.png

Ich würde es so machen, dass der erzeugende Prozess die Grafik grafik_new.png erzeugt, dann die grafik.png in grafik_old.tmp umbenennt und danach die grafik_new.png in grafik.png umbenennt und die grafik_old.png löscht oder in ein Archiv schiebt.
Muss auch nicht grafik_old.png sein, sondern kann ja grafik_TIMESTAMP.png sein damit da nix passiert wenn die grafik_old.png nicht gelöscht werden konnte.

Dieses Umbenennen sollte nicht lange dauern, das heisst du kannst beim Lesen der Datei erstmal schauen ob die grafik.png existiert, wenn nicht warten.

Am besten zu zählst da einen Counter hoch, weil man davon ausgehen dürfte, dass die Datei nicht länger als zB 2 Sekunden weg sein dürfte. Ist der Counter zu hoch, gibst du ne Fehlergrafik aus, das es Probleme beim Erzeugen der grafik.png gibt.
Nicht vergessen bei erfolgreichem Ausgeben den Counter wieder zurückzusetzen falls das -je nach Konstrukt - nötig sein sollte.

alzaimar 11. Sep 2009 07:08

Re: 1 Datei und 2 Prozesse ...
 
Zitat:

Zitat von moelski
Ich klammere deshalb das ganze Lesen mit dem Inkementieren und Dekrementieren eines Counter - nennen wir ihn mal Z.

Fast richtig. Nur das 'Z' nicht threadsicher ist. Wenn die Threads gleichzeitig Z verändern, kippt dieses System. Garantiert.
Verwende also einfach eine Semaphore oder innerhalb einer Anwendung (aber unterschiedlichen Threads!) eine 'TCriticalSection'.

So schützt Du den Zugriff, sorgst also dafür, das garantiert nur maximal ein Thread die Resource benutzen kann:
Delphi-Quellcode:
uses SyncObjs;
...
FileCriticalSection := TCriticalSection.Create;
...
// Thread1:
...
FileCriticalSection.Enter;
Try
  WriteTheFile;
Finally
  FileCriticalSection.Leave;
End;
...

// Thread2:
...
FileCriticalSection.Enter;
Try
  ReadTheFile;
Finally
  FileCriticalSection.Leave;
End;
...

moelski 11. Sep 2009 07:16

Re: 1 Datei und 2 Prozesse ...
 
Moin !

@alzaimar:
Und in WriteTheFile / bzw. ReadTheFile würde ich dann meinen Code zum Lesen bzw. Schreiben der Datei packen?
Oder darein nur den Counter bearbeiten?

Blup 11. Sep 2009 10:23

Re: 1 Datei und 2 Prozesse ...
 
Das jetzigen Konzept ist wohl so:
Code:
DatenSection TCriticalSection
GrafikSection TMultiReadExclusiveWriteSynchronizer

Speichern-Thread:
- Enter DatenSection
  - Daten entgegen nehmen und speichern
  - Prüfen letzter Grafikerstellungszeitpunkt und ob Daten neue Daten vorhanden, wenn erforderlich
    - Enter GrafikSection schreiben
      - Daten lesen
      - Grafik erstellen
      - Schreiben Grafikerstellungszeitpunkt
    - Exit GrafikSection schreiben
- Exit DatenSection

Webseite-Thread:
- Enter GrafikSection lesen
  - Grafik lesen
- Exit GrafikSection lesen
Ich würde die Grafik nur dann erstellen, wenn diese auch wirklich gebraucht wird:
Code:
DatenSection TCriticalSection
GrafikSection TMultiReadExclusiveWriteSynchronizer

Speichern-Thread:

- Daten entgegen nehmen
- Enter DatenSection
  - Daten speichern
- Exit DatenSection

Webseite-Thread:
- Enter DatenSection
  - Prüfen letzter Grafikerstellungszeitpunkt und ob Daten neue Daten vorhanden, wenn erforderlich
    - Enter GrafikSection schreiben
      - Daten lesen
      - Grafik erstellen
      - Schreiben Grafikerstellungszeitpunkt
    - Exit GrafikSection schreiben
- Exit DatenSection
- Enter GrafikSection lesen
  - Grafik lesen
- Exit GrafikSection lesen

moelski 11. Sep 2009 10:41

Re: 1 Datei und 2 Prozesse ...
 
Moin !

@Blup:
Das mit dem Grafik schreiben ist so eine Sache. Die Grafik steht bereits und ich möchte auch nicht eine neue Grafik berechnen lassen. Das kostet alles Zeit.

Ich habe aber jetzt dank alzaimar die Sache mit TCriticalSection versehen. Und siehe da, all meine Probleme haben sich wie von Zauberhand gelöst.
Habe schon seit Stunden einen Test am rennen mit mehreren Webbrowsern parallel. Bis jetzt keinerlei Probleme.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:58 Uhr.
Seite 2 von 3     12 3      

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