Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi E/A-Fehler 103 bei Speichern mittels FileStream (https://www.delphipraxis.net/71267-e-fehler-103-bei-speichern-mittels-filestream.html)

MStoll 12. Jun 2006 11:28


E/A-Fehler 103 bei Speichern mittels FileStream
 
Hi

ich bekomme bei folgendem Code sporadisch E/A-Fehler 103. Dies ist eine Speicher-Prozedur aus einer DLL, die mit verschiedenen Programmen auf verschiedenen Rechnern verwendet wird. Ich muss dazusagen, dass mittels diesen Codes 1 Programm dauernd in eine Datei schreibt, während 2 andere Programme auf 2 anderen Rechnern in festen Intervallen lesend auf sie zugreifen. Sozusagen ein asynchroner Zugriff von 3 Parteien.

Delphi-Quellcode:
procedure save_zeiten_rdt_(const filename : string; const zeiten : tzeiten; count : integer = 1);
var fs : TFileStream;
    x, i : integer;
begin
     fs := nil;
     i := 0;

     {$I-}
     while (fs = nil) and (i < 10) do
     begin
          try
             fs := TFileStream.Create(filename, fmCreate or fmShareExclusive);
          except
             if fs <> nil then
                fs := nil;
          end;
          Sleep(5);
          inc(i);
     end;
     {$I+}
     
     if ((IOResult <> 0) or (fs = nil)) and (count < 5) then
     begin
          Sleep(50);
          save_zeiten_rdt_(filename, zeiten, count+1);
          fs := nil;
     end
     else if count >= 5 then
          exit;

     if fs = nil then
        exit;

     try
        try
           for x := 0 to high(zeiten) do
               fs.WriteBuffer(zeiten[x].zeit, sizeof(zeiten[x].zeit));
        finally
            fs.Free;
        end;
     except
     end;

     if length(zeiten) = 0 then
        SysUtils.DeleteFile(filename);
end;
Die Leseprozedur sieht so aus:
Delphi-Quellcode:
function read_zeiten_rdt(const filename : string; out ok : boolean; out fehlercode : integer) : tzeiten;
var x, i : integer;
    fs : TFileStream;
begin
       ok := true;
       fehlercode := 0;

       x := 0;
     i := 0;
     fs := nil;
       SetLength(result, x);

       if fileexists(filename) then
       begin
          while (fs = nil) and (i < 10) do
          begin
               try
                  fs := TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
               except
                  if fs <> nil then
                     fs := nil;
               end;
               Sleep(5);
               inc(i);
          end;

          if fs = nil then
          begin
               ok := false;
               fehlercode := fdio;
               exit;
          end;

          try
             fs.Position := 0;
             while fs.Position < fs.Size do
             begin
                  SetLength(result, x+1);
                  try
                     fs.read(result[x].zeit, sizeof(tzeit));
                     result[x].ID := x;
                  except
                     SetLength(result, 0);
                     ok := false;
                     fehlercode := fdtype;
                     break;
                  end;
                  inc(x);
             end;
          finally
             fs.Free;
          end;
     end
     else
     begin
          ok := false;
          fehlercode := fdnofile;
     end;
end;
Der E/A-Fehler tritt allerdings nur bei der Schreib-Prozedur auf. Diese Prozedur wird von einem Hintergrundthread aufgerufen, der allein für das Schreiben dieser einen Datei zuständig ist.

Hat jemand eine Idee, was ich dagegen tun kann? Ich hab schon mehrere Sachen versucht, total überladene try...except-Konstrukte, Die E/A-Prüfung ausgeschaltet etc. Aber diese Exception mit dem E/A-Fehler dringt irgendwie immer bis ins Hauptprogramm durch (Auch wenn ich zugegebenermaßen noch kein Problem mit der Datei bemerkt hab, lediglich der Fehler an sich stört mich.)

Gruß Michael

Luckie 12. Jun 2006 11:34

Re: E/A-Fehler 103 bei Speichern mittels FileStream
 
Zitat:

103 File not open
Damit sollte klar sein, was los ist. Die Datei wird wohl nicht zum Schreiben geöffnet werden können.

MStoll 12. Jun 2006 11:51

Re: E/A-Fehler 103 bei Speichern mittels FileStream
 
@Luckie: Das weiß ich, allerdings sollte die Prozedur doch abbrechen, wenn sie nicht geöffnet werden konnte. Oder findest du da einen Fehler?

shmia 12. Jun 2006 12:21

Re: E/A-Fehler 103 bei Speichern mittels FileStream
 
Um auf eine Datei exklusiv zuzugreifen, gibt's in der Code-Library eine spezielle Klasse:
http://www.delphipraxis.net/internal...ct.php?t=62072

MStoll 12. Jun 2006 12:29

Re: E/A-Fehler 103 bei Speichern mittels FileStream
 
Danke für die Antwort, aber nix anderes mach ich doch auch, wenn ich dem FileStream die Konstante fmShareExclusive mitgebe bzw. beim Lesen fmShareDenyWrite. Gleichzeitiges reines Lesen sollte ja möglich sein, oder?

Luckie 12. Jun 2006 12:33

Re: E/A-Fehler 103 bei Speichern mittels FileStream
 
eben nicht. enn du sie exklusiv öffnest, dann kan nkein anderer prozess auf sie zugreifen so lange sie geöffnet ist.

BTW hat {I+/-} nur Auswirkungenm, wenn mir den alten Pascal Dateiroutinen gearbeitet wird.

MStoll 12. Jun 2006 13:02

Re: E/A-Fehler 103 bei Speichern mittels FileStream
 
Gab's da nicht mal so etwas ähnliches bei synchronisierten Threads. Schreiben muss exklusiv sein, Lesen hingegen dürfen mehrere ohne Probleme?

[Edit]
Zitat:

fmShareExclusive Andere Anwendungen können die Datei nicht öffnen
fmShareDenyWrite Andere Anwendungen können die Datei ausschließlich zum Lesen öffnen.
Auszug aus der Delphi-Hilfe. D.h. doch, wenn ich zum Schreiben öffnen will und ein anderer Prozess liest gerade, dann müsste doch das Öffnen verweigert werden, oder?
Genauso, wenn ich zum Lesen öffnen will und ein anderer Prozess schreibt gerade. Davon bin ich jedenfalls ausgegangen. Das Problem ist ja, dass die Prozedur, wenn das Öffnen fehlgeschlagen ist, wohl zu schreiben versucht statt das Öffnen neu zu versuchen. Warum weiß ich leider nicht.

@Luckie: Na dann lass ich das {$I-} und {$I+} mal wieder weg. War eh nur ein FastHack, weil mir sonst nix mehr eingefallen ist. Danke für den Hinweis.

Meint ihr, es würde was bringen, wenn ich beim Lesen auch fmShareExclusive benutze? Wenn nein, was ist dann genau der Unterschied zwischen FileStream mit fmShareExclusive und dem TExclusiveFileStream?
[/Edit]

shmia 12. Jun 2006 14:24

Re: E/A-Fehler 103 bei Speichern mittels FileStream
 
Zitat:

Zitat von MStoll
Wenn nein, was ist dann genau der Unterschied zwischen FileStream mit fmShareExclusive und dem TExclusiveFileStream?

Wenn du diese Klasse benützt, dann brauchst du dich nicht selbst um die mehrfachen Öffnungsversuche zu kümmen:
Delphi-Quellcode:
  // versuche max. 3sek die Datei exklusiv zu öffnen
  stream := TExclusiveFileStream('C:\test.log', 3000);
Bei deiner Variante mit der Schleife bleibt der Debugger bei der Exception stehen, falls Sprachexeceptions aktivert sind; dass stört das Debuggen.
TExclusiveFileStream gibt auch sofort auf, wenn die Datei aus anderen Gründen (falsches Verz.)
zu öffnen ist und wartet nicht "ewig".

MStoll 12. Jun 2006 15:35

Re: E/A-Fehler 103 bei Speichern mittels FileStream
 
Ok, ich werd's dann mal GANZ exklusiv ausprobieren. Danke für eure Hinweise! :thumb:


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