Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Und nochmal ne Frage zu Streams... (https://www.delphipraxis.net/3435-und-nochmal-ne-frage-zu-streams.html)

janjan 12. Mär 2003 15:10


Und nochmal ne Frage zu Streams...
 
Ich hab in meinem Projekt zwei Streams:

Delphi-Quellcode:
var
  DateiStream: TFileStream;
  MemoryStream: TMemoryStream;
Den MemoryStream benutz ich als Buffer und schreib da ca. 10 mal pro Sekunde einen String rein. Um das ganze in eine Datei zu schreiben benutz ich einen Timer eingestellt auf ca. 15-30 Sekunden.

Das OnTimer-Ereignis sieht folgendermaßen aus:

Delphi-Quellcode:
procedure TForm1.SpeicherTimerTimer(Sender: TObject);
begin
  MemoryStream.SaveToStream(DateiStream);
  MemoryStream.Clear;
end;
Ich schreibe den MemoryStream erst in eine Datei und lösche ihn dann um wieder neue Daten aufnehmen zu können.

Jetzt meine Frage:

Kann es passieren, das ich Daten 'verpasse' wenn sie zufällig genau zwischen dem SaveToStream und dem Clear eintreffen und in MemoryStream gespeichert werden?

Das da Daten ins Nirvana verschwinden hab ich anhand eines Vergleiches der gesendeten und empfangenen Daten festgestellt. Dummerweise hab ich keine Ahnung wo das passiert...

sakura 12. Mär 2003 15:23

Ja, das kann passieren, falls Du mit Threads arbeitest, ansonsten dürfte es recht sicher sein. Zum Synchronisieren bietet die Standard-Version von Delphi leider keine Möglichkeiten, aber schau mal bei http://msdn.microsoft.com nach Critical Section, die sind auch so recht leicht zu implementieren. Damit kannst Du das Problem umgehen.

...:cat:...

Sharky 12. Mär 2003 15:24

Re: Und nochmal ne Frage zu Streams...
 
Zitat:

Zitat von janjan
..
Delphi-Quellcode:
procedure TForm1.SpeicherTimerTimer(Sender: TObject);
begin
  MemoryStream.SaveToStream(DateiStream);
  MemoryStream.Clear;
end;
....
Kann es passieren, das ich Daten 'verpasse' wenn sie zufällig genau zwischen dem SaveToStream und dem Clear eintreffen und in MemoryStream gespeichert werden?
...

Hai JanJan,

ich gehe mal davon aus das folgendes passiert.
1. Du schreibst den Stream in eine Datei.
2. Während er geschrieben wird kommen neue Daten in den Stream
3. Da Du nach dem Speichern den Stream löschst sind die Daten die während des speicherns hinzugekommen sind futsch.

Eine mögliche lösung wäre eventuell mit zwei Streams zu arbeiten.

1. aktueller Stream = Stream1
2. Daten werden in Stream 1 geschrieben
3. Vor dem Speichern: aktueller Stream = Stream2
4. Daten werden jetzt in Stream 2 geschrieben
5. Stream 1 speichern.

usw.

janjan 13. Mär 2003 08:22

@Sharky:

Danke für den Vorschlag, sowas in die Richtung hab ich mir auch gedacht, aber das ist alles irgendwie hingebastelt, ich suche eine 'richtige' Lösung für das Problem.

@Luckie:
Das sieht schonmal gut aus, aber so ganz verstehe ich das noch nicht. In Delphi gibts es ja ein entsprechendes Objekt namens TCriticalObject, aber irgenwie gibts da wenig Infos zu.

Bei mir im Quelltext sieht es z.Z. so aus:

Delphi-Quellcode:
var
  DateiStream: TFileStream;
  MemoryStream: TMemoryStream;
  CS: TCriticalSection;
  {...}
CS:= TCriticalSection.Create;
...
Delphi-Quellcode:
procedure TForm1.SpeicherTimerTimer(Sender: TObject);
begin
  MemoryStream.SaveToStream(DateiStream);
  MemoryStream.Clear;
end;
Und dann gibts da noch ein paar Routinen die die Daten in den MemoryStream schreiben:

Delphi-Quellcode:
// Paket1 wurde empfangen
procedure TForm1.Paket1StringPacket(Sender: TObject; Data: String);
begin
  Paket1:= data;
  MemoryStream.WriteBuffer(data[1],Length(data));
  {...}
end;

// Paket2 wurde empfangen
procedure TForm1.Paket2StringPacket(Sender: TObject; Data: String);
begin
  Paket2:=data;
  MemoryStream.WriteBuffer(data[1],Length(data));
  {...}
end;
Die PaketEmpfangsRoutinen werden von TApdDataPacket-Komponenten aus der Async Sammlung aufgerufen. das passiert immer dann, wenn die Paketkomponente am Com-Port ein vorher eingestelltes Paket entdeckt.


So wie ich das jetzt verstanden habe muss ich das CS.Acquire und das CS.Release einmal in die Paket-Routinen und einmal in das TimerEreignis einbauen, stimmt das so?

janjan 14. Mär 2003 11:09

*schieb*

:oops:


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