![]() |
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 ... :| |
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.
|
Re: 1 Datei und 2 Prozesse ...
Moin !
Zitat:
Ok man könnte die Grafik dann in einem Thread erzeugen lassen. Aber dann steigt der Aufwand für diese Grafik doch enorm. |
Re: 1 Datei und 2 Prozesse ...
Deshalb ja bei Bedarf. Die Werte werden nur gespeichert und bei Anforderung durch Browser erzeugt.
|
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:
Sowas widerstrebt mir irgendwie genauso wie Sleep Aufrufe.
while FileInUse(LPathname) do Application.ProcessMessages;
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:
Daraus kann man dann folgende Schlüsse ziehen:
INC(Z);
//.... HTTPServer_CommandGet Code DEC(Z); - 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:
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.
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); Evtl. könnte man das auch noch etwas abfangen wenn man nach dem INC(Z) erst ein
Delphi-Quellcode:
aufrufen würde.
BlockReading := (Z = 1) AND (SaveDone = True);
Jedenfalls wäre das eine Lösung die ohne grossartige Sleeps oder sonstige Wartezyklen auskäme. Oder habe ich was gravierendes übersehen !? |
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. |
Re: 1 Datei und 2 Prozesse ...
Zitat:
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; ... |
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? |
Re: 1 Datei und 2 Prozesse ...
Das jetzigen Konzept ist wohl so:
Code:
Ich würde die Grafik nur dann erstellen, wenn diese auch wirklich gebraucht wird:
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
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 |
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. |
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