Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: TIniFile und Terminal-Server

  Alt 15. Nov 2013, 11:49
Und dann kannst du das mal mit dieser von TIniFile abgeleiteten Klasse versuchen
Bei jedem Zugriff auf die Datei wird erst der Mutex betreten und danach wieder verlassen.
Delphi-Quellcode:
unit MutexIniFile;

interface

uses
  System.Classes,
  System.SyncObjs,
  System.SysUtils,
  System.IniFiles;

type
  TMutexIniFile = class( TIniFile )
  private
    FMutex : TMutex;
    FUpdateLock : Integer;
  protected
    function GetMutexName : string; virtual;
  public
    constructor Create( const FileName : string );
    destructor Destroy; override;

    function ReadString(const Section, Ident, Default: string): string; override;
    procedure WriteString(const Section, Ident, Value: String); override;
    procedure ReadSection(const Section: string; Strings: TStrings); override;
    procedure ReadSections(Strings: TStrings); override;
    procedure ReadSectionValues(const Section: string; Strings: TStrings); override;
    procedure EraseSection(const Section: string); override;
    procedure DeleteKey(const Section, Ident: String); override;
    procedure UpdateFile; override;

    procedure BeginUpdate;
    procedure EndUpdate;
  end;

implementation

{ TMutexIniFile }

procedure TMutexIniFile.BeginUpdate;
begin
  if FUpdateLock = 0
  then
    FMutex.Acquire;
  Inc( FUpdateLock );
end;

constructor TMutexIniFile.Create( const FileName : string );
begin
  inherited;
  FMutex := TMutex.Create( nil, False, 'Global\' + GetMutexName );
end;

procedure TMutexIniFile.DeleteKey( const Section, Ident : string );
begin
  BeginUpdate;
  try
    inherited;
  finally
    EndUpdate;
  end;
end;

destructor TMutexIniFile.Destroy;
begin
  while FUpdateLock > 0 do
    EndUpdate;

  FMutex.Free;
  inherited;
end;

procedure TMutexIniFile.EndUpdate;
begin
  Dec( FUpdateLock );
  if FUpdateLock = 0
  then
    FMutex.Release;
end;

procedure TMutexIniFile.EraseSection( const Section : string );
begin
  BeginUpdate;
  try
    inherited;
  finally
    EndUpdate;
  end;
end;

function TMutexIniFile.GetMutexName : string;
  function HashOf( const Key : string ) : Cardinal;
  var
    I : Integer;
  begin
    Result := 0;

    for I := 0 to Key.Length - 1 do
      begin
        Result := ( ( Result shl 2 ) or ( Result shr ( SizeOf( Result ) * 8 - 2 ) ) ) xor Ord( Key.Chars[I] );
      end;
  end;

begin
  Result := Format( 'inifile_%.8x', [HashOf( FileName )] );
end;

procedure TMutexIniFile.ReadSection( const Section : string; Strings : TStrings );
begin
  BeginUpdate;
  try
    inherited;
  finally
    EndUpdate;
  end;
end;

procedure TMutexIniFile.ReadSections( Strings : TStrings );
begin
  BeginUpdate;
  try
    inherited ReadSections( Strings );
  finally
    EndUpdate;
  end;
end;

procedure TMutexIniFile.ReadSectionValues( const Section : string; Strings : TStrings );
begin
  BeginUpdate;
  try
    inherited;
  finally
    EndUpdate;
  end;
end;

function TMutexIniFile.ReadString( const Section, Ident, Default : string ) : string;
begin
  BeginUpdate;
  try
    Result := inherited;
  finally
    EndUpdate;
  end;
end;

procedure TMutexIniFile.UpdateFile;
begin
  BeginUpdate;
  try
    inherited;
  finally
    EndUpdate;
  end;
end;

procedure TMutexIniFile.WriteString( const Section, Ident, Value : string );
begin
  BeginUpdate;
  try
    inherited;
  finally
    EndUpdate;
  end;
end;

end.
Die Hash-Routine für den Dateinamen ist eine sehr einfache und kann bei Bedarf auch gewechselt werden.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat