Einzelnen Beitrag anzeigen

Lothar

Registriert seit: 26. Apr 2007
Ort: München
12 Beiträge
 
Turbo Delphi für Win32
 
#1

Filestream.Lock: Rätselhaftes Verhalten

  Alt 30. Apr 2007, 15:59
Hallo!

Ich kämpfe seit 2 Tagen mit einem Problem beim Filelocking, für das ich keine Lösung finden kann. Um die Sache klarer zu machen, habe ich alles auf ein einfaches Testprogramm reduziert, wo ich die Schwierigkeit lokalisieren kann:

Ich schreibe z.B. 20.000 Mal 8 Bytes hintereinander in eine neue Datei. Dann setze ich einen Lock auf irgendeinen Datenbereich dieser 8 Bytes, z.B. beim 1000-sten Satz. Wenn ich dann mit einem zweiten Aufruf dieses Programms (Parallelausführung) auf diese 8 Bytes mit "Lesen_iClick" zugreife (oder auch mit derselben Instanz), kommt genau das erwartete Verhalten: es wird nämlich gemeldet, daß der Bereich gelocked ist. Kurioserweise bekomme ich aber bei den darunterliegenden Daten bei "Lesen_iClick" eine IOException, obwohl dort gar nichts gelocked ist! Und zwar bis zu einem Bereich von exakt Satz-Nr. 489, also ca. 4096 Bytes unterhalb; ansonsten kann ich normale Lesezugriffe machen (also vom Dateistart an bis zu diesem kritischen Bereich, also bis Satz-Nr. 488, und außerdem direkt oberhalb dem gelockten Bereich, also ab Satz 1001).

Die IOException würde ja bedeuten, daß etwas gesperrt ist, aber es ist eben NICHTS gesperrt. Trotz aller Versuche kriege ich den Fehler nicht weg! Ich wäre daher für jede Art Hilfe äußerst dankbar.

Hier Teile aus der Source:

Delphi-Quellcode:
type
   NRec = record
      a,b,c,d,e,f,g,h: byte;
   end;

   private
      N_recsize: integer;
      N_Datei: FileStream;
      procedure N_Close;
      function N_OpenCreate: boolean;
      function N_Lock (i:integer): boolean;
      function N_UnLock (i:integer): boolean;
      function N_Lesen (i:integer; var NSatz:NRec{a,b,c,d,e,f,g,h: byte}): boolean;
      procedure N_Locktest (i:integer; bLock:boolean);

...


procedure THaupt2F.N_Close;
begin
   try
      N_Datei.Free;
   except
      Msg('# N_close');
   end;
end;

function THaupt2F.N_OpenCreate: boolean;
begin
   result:=TRUE;
   try
      N_Datei:=Filestream.Create('test.dat',
         FileMode.OpenOrCreate,
         FileAccess.ReadWrite,FileShare.ReadWrite);
   except
      Msg('#OpenorCreate');
      result:=FALSE;
   end;
   N_recsize:=8;
end;

function THaupt2F.N_Lock (i:integer): boolean;
begin
   result:=TRUE;
   try
      N_Datei.Lock(i*N_recsize,1{N_recsize}); {-> der Einfachheit halber nur 1 Byte gelocked}
   except
      Msg(inttostr(i)+' schon locked');
      result:=FALSE;
   end
end;

function THaupt2F.N_UnLock (i:integer): boolean;
begin
   result:=TRUE;
   try
      N_Datei.UnLock(i*N_recsize,1{N_recsize}); {-> s.o.}
   except
      Msg('Unlock '+inttostr(i)+' fail');
      result:=FALSE;
   end;
end;

procedure THaupt2F.AnlegenSchreibenClick(Sender: TObject);
var i,j: integer;
      Writer: BinaryWriter;
      Buffer: array [1..8] of byte;
begin
   if NOT N_OpenCreate then exit;

   Writer:=BinaryWriter.Create(N_Datei);

   for i:=0 to 19999 do
      begin
         for j:=1 to 7 do Buffer[j]:=0; Buffer[8]:=i; { 1 Eintrag }
         Writer.Write(Buffer);
      end;

   N_Close;
end;

function THaupt2F.N_Lesen (i:integer; var NSatz:NRec{a,b,c,d,e,f,g,h:byte}): boolean;
var Reader: BinaryReader;
begin
   result:=TRUE;

   Reader:=BinaryReader.Create(N_Datei);

   with NSatz do
   try
      N_Datei.Seek(i*N_recsize,SeekOrigin.Begin);

      a:=Reader.ReadByte;   b:=Reader.ReadByte;
      c:=Reader.ReadByte;   d:=Reader.ReadByte;
      e:=Reader.ReadByte;   f:=Reader.ReadByte;
      g:=Reader.ReadByte;   h:=Reader.ReadByte;
   except
      on IOException do
         begin
            Msg('# IOException');
            result:=FALSE;
         end;
   end;
end;

procedure THaupt2F.Lesen_iClick(Sender: TObject);
var i:integer;
      NSatz: NRec; {a,b,c,d,e,f,g,h: byte;}
begin
   AListe.clear;

   try
      i:=strtoint(Edit1.Text);
   except
      exit
   end;

   if NOT N_OpenCreate then exit;

   if N_Lock(i) then
      begin
         if NOT N_Lesen(i,NSatz{a,b,c,d,e,f,g,h}) then
               begin N_close; exit end;
         N_UnLock(i);

         with NSatz do
            AListe.Items.add(a.ToString+' '+
               b.ToString+' '+
               c.ToString+' '+
               d.ToString+' '+
               e.ToString+' '+
               f.ToString+' '+
               g.ToString+' '+
               h.ToString);
      end;
   N_close;
end;

procedure THaupt2F.N_Locktest (i:integer; bLock:boolean);
begin
   if bLock then
      begin
         if NOT N_OpenCreate then exit;
         if N_Lock(i) then;
      end
   else
      begin
         if N_UnLock(i) then;
         N_close;
      end;
end;

...

procedure THaupt2F.Lock1000Click(Sender: TObject);
begin   N_Locktest(1000,TRUE); end;

...

procedure THaupt2F.UnLock1000Click(Sender: TObject);
begin N_Locktest(1000,FALSE); end;
Die ominöse Exception tritt beim ersten Reader.ReadByte in N_Lesen auf, nachdem das vorangegangene N_Lock(i) problemlos durchgegangen war.

Ich hoffe, ich habe mich verständlich ausgedrückt, sonst bitte nachfragen!

Grüße
Lothar
  Mit Zitat antworten Zitat