Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Library: Dateien / Laufwerke (https://www.delphipraxis.net/41-library-dateien-laufwerke/)
-   -   Delphi Exclusiver Zugriff auf Dateien (https://www.delphipraxis.net/52135-exclusiver-zugriff-auf-dateien.html)

shmia 24. Aug 2005 10:57


Exclusiver Zugriff auf Dateien
 
Liste der Anhänge anzeigen (Anzahl: 1)
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;


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