0

いくつかのファイルを処理する複数のサービスがあります。各サービスは、処理中にファイルに排他的にアクセスする必要があります。少し前に、次のような一時ファイルを使用するグローバル ミューテックスを作成することで、この問題を解決しました。

function AppLocked: boolean;
begin
  result := FileExists(GetTempDir + '__MUTEX__' + LockExt);
end;

procedure AppLock;
var
  F: TextFile;
begin
  if FileExists(GetTempDir + '__MUTEX__' + LockExt) then
    exit
  else
  try
    AssignFile(F, GetTempDir + '__MUTEX__' + LockExt);
    Rewrite(F);
    Writeln(F, DateTimeToStr(Now));
    CloseFile(F);
  except
  end;
end;

procedure AppUnLock;
begin
  if FileExists(GetTempDir + '__MUTEX__' + LockExt) then
    SysUtils.DeleteFile(GetTempDir + '__MUTEX__' + LockExt);
end;

これはかなりうまく機能し、機能するものを修正したくありませんが、もっと良い解決策はあるのでしょうか?

4

2 に答える 2

4

実際のMutex(win32 Mutexなど)が推奨される方法です。

于 2012-11-09T22:16:20.477 に答える
1

アプリケーションが終了し、ロックを解除できなかった場合、ソリューションに問題があります。これは、異常終了時に発生する可能性があります。アプリケーションが終了すると自動的に消去されるファイルを作成することをお勧めします。

すべての魔法はFILE_FLAG_DELETE_ON_CLOSEによって行われます

unit uAppLock;

interface

function AppLocked : Boolean;
function AppLock : Boolean;
procedure AppUnlock;

implementation

uses
  Windows, SysUtils, Classes;

var
  // unit global variable 
  LockFileHandle : THandle;

// function to build the filename
function GetLockFileName : string;
begin
  // You have to point out, where to get these informations
  Result := GetTempDir + '__MUTEX__' + LockExt;
end;

function AppLocked : Boolean;
begin
  Result := FileExists( GetLockFileName );
end;

function AppLock : Boolean;
var
  LFileName :       string;
  LLockFileStream : TStream;
  LInfoStream :     TStringStream;
begin
  Result := False;

  if AppLock
  then
    Exit;

  LFileName := GetLockFileName;

  // Retrieve the handle of the LockFile
  LockFileHandle := CreateFile( PChar( LFileName ), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_DELETE,
    nil, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE or FILE_ATTRIBUTE_TEMPORARY, 0 );

  if LockFileHandle <> INVALID_HANDLE_VALUE
  then
    begin

      Result := True;

      LInfoStream     := nil;
      LLockFileStream := nil;
      try

        LInfoStream := TStringStream.Create;
        LInfoStream.WriteString( DateTimeToStr( Now ) );
        LInfoStream.Seek( 0, soFromBeginning );

        LLockFileStream := THandleStream.Create( LockFileHandle );
        LLockFileStream.CopyFrom( LInfoStream, LInfoStream.Size );

      finally
        LInfoStream.Free;
        LLockFileStream.Free;
      end;

    end;

end;

procedure AppUnlock;
begin
  // Just close the handle and the file will be deleted
  CloseHandle( LockFileHandle );
end;

end.

ところで: GetTempDirはディレクトリのように見えますが、パスとして使用します。そのため、代わりにGetTempPathに名前を変更することをお勧めします:o)

于 2012-11-10T03:09:40.400 に答える