2012-11-09 4 views
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; 

이 꽤 잘 작동하고, 나는 작동 뭔가를 해결하고 싶지 않아,하지만 난 그냥 궁금 더 나은 해결책이 있습니까?

+0

어떤 Delphi 버전을 사용하고 있습니까? 적어도 D2007을 통해 Delphi 버전에 포함 된 프로세스 간 통신 (Demos \ DelphiWin32 \ VCLWin32 \ IPCDemos 폴더에 있음)의 꽤 좋은 예가 있습니다. 최신 버전에는 Samples \ Delphi \ RTL \ SimpleShareMem 데모가 있습니다. –

+0

저는 Delphi XE를 사용하고 있습니다. 나는 그 예를 발견했고 지금 당장 그것을 연구하고있다. 감사. –

+0

파일을 연 프로세스가 파일을 닫지 않는 한 '다시 쓰기'가 이미 다른 프로세스에서 실패합니다. –

답변

4

실제 뮤텍스 (win32 뮤텍스에서와 같이)가 선호되는 방법입니다.

+1

이것은 대답이 아닙니다. 그것은 질문이나 제안이며, 대신 의견으로 게시해야합니다. 대답이되기를 원한다면 내용을 추가하여 내용을 추가하고 질문 대신 대답으로 사용해야합니다. –

+0

의견을 보내 주셔서 감사합니다. 편집 됨. –

+0

글쎄, 원래 뮤텍스로 임시 파일을 사용하기 전에 전역 전역 뮤텍스를 사용하여 시도했지만 * 기억한다면 * 문제가있는 Windows 버전이있었습니다. 내가 사용하는 코드 중 일부는 Windows NT가 주위에있을 때 작성했습니다 ... 그리고 기억한다면 Windows의 일부 버전이있는 일부 컴퓨터에서 전역 뮤텍스가 글로벌이 아니 었습니다 (적어도 만들 수는 없었습니다. 일) ... 그래서 나는 파일을 사용하기로 결정했다. 아마 win32 mutex에 또 다른 시도를 해줘야할까요? –

1

응용 프로그램이 종료되고 잠금 해제하지 못한 경우 솔루션에 문제가 있습니다. 이것은 비정상 종료시 발생할 수 있습니다. 응용 프로그램이 종료되면 자동으로 지워지는 파일을 만드는 것이 좋습니다.

모든 마법은

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. 

BTW FILE_FLAG_DELETE_ON_CLOSE에 의해 수행됩니다 GetTempDir이 디렉토리로 보이는,하지만 당신은 경로로 사용합니다. 따라서 이름을 으로 바꾸는 것이 좋습니다. GetTempPath 대신 :

+0

감사합니다. 아주 좋은 조언입니다. 나는 뮤텍스로 파일을 사용해야하는 상황에서 이것을 염두에 두겠다. 지금은 TMutex를 테스트하고 있으며 지금까지 그렇게 훌륭합니다. –

관련 문제