Einzelnen Beitrag anzeigen

shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#1

Exclusiver Zugriff auf Dateien

  Alt 24. Aug 2005, 10:57
Häufig ist es nötig, exclusiven Zugriff auf eine Datei zu haben.
Wenn z.B. 20 Rechner im Netzwerk in eine Log-Datei schreiben, darf immer nur ein Prozess die Datei offen haben. (siehe auch Bei Google suchenMutex)

Dazu gibt es nun die Klasse TExclusiveFileStream.
Zu TFileStream gibt es folgende Unterschiede:
* Falls die Datei noch nicht exisitiert, wird sie erzeugt
* der Zugriff erlaubt immer Lese- & Schreibzugriff
* kein anderer Prozess kann die Datei lesen oder schreiben, solange ein Objekt der Klasse existiert
* es kann ein Timeout angegeben werden. Innerhalb dieser Zeit (in ms) wird versucht die Datei zu öffnen/erzeugen. übliche Zeiten liegen zwischen 200ms und 10s.
* Während des Wartens, bis die Datei frei wird, wird das Event OnWait "abgefeuert". Dies erlaubt dem Programm, das Warten sichtbar zu machen
* Falls die Datei nicht geöffnet werden konnte, enthält die Exception ein aussagekräfte Meldung, warum es nicht geklappt hat

TExclusiveFileStream wurde sorgfältig (von mir getestet.
Es existiert dazu eine Testanwendung (multithreaded), deren Sourcecode sich im Anhang befindet.

Die Funktion GetTickCount wurde so verwendet, dass nach 49,7 Tagen kein Overflow Problem entsteht.


Delphi-Quellcode:
  TExclusiveFileStream = class(THandleStream)
  private
    FFileName : string;
  public
    constructor Create(const FileName: string; timeout:Cardinal; OnWait:TNotifyEvent=nil);
    destructor Destroy; override;
    procedure SeekToEnd;
    property FileName:string read FFileName;
  end;

{ TExclusiveFileStream }

constructor TExclusiveFileStream.Create(const filename: string; timeout: Cardinal; OnWait: TNotifyEvent);
const
   FILE_SHARE_EXCLUSIVE = 0;
var
   hnd : THandle;
   curtime, starttime : Cardinal;
   error : DWORD;
begin
   FFileName := FileName;
   starttime := GetTickCount;

   while true do
   begin
      hnd := CreateFile(PChar(filename), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_EXCLUSIVE,
         nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

      if hnd <> INVALID_HANDLE_VALUE then
      begin
         inherited Create(hnd);
         Exit;
      end;

      error := GetLastError;
      curtime := GetTickCount;
      if ((curtime - starttime) >= timeout) or
         ((error<>ERROR_SHARING_VIOLATION) and (error<>ERROR_LOCK_VIOLATION)) then
         raise EFOpenError.CreateFmt(SFOpenError+#13#10+
            SysErrorMessage(error), [FileName]);

      if Assigned(OnWait) then
         OnWait(Self);
      Sleep(100);
   end;
end;

destructor TExclusiveFileStream.Destroy;
begin
   if DWORD(Handle) <> INVALID_HANDLE_VALUE then
      FileClose(Handle);
end;

procedure TExclusiveFileStream.SeekToEnd;
begin
   Seek(0, soFromEnd);
end;
Angehängte Dateien
Dateityp: zip filestreamtest_161.zip (5,4 KB, 140x aufgerufen)
Andreas
  Mit Zitat antworten Zitat