2012-11-09 24 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(在Demos \ DelphiWin32 \ VCLWin32 \ IPCDemos文件夾中),Delphi版本中包含了一個相當好的進程間通信示例;在更新的版本中,有Samples \ Delphi \ RTL \ SimpleShareMem演示。 –

+0

我正在使用Delphi XE。我找到了這個例子,我現在正在研究它。謝謝。 –

+0

我沒有看到重點,除非打開文件的進程關閉它,否則'重寫'已經失敗。 –

回答

4

實際互斥鎖(如在win32互斥鎖中)是首選方法。

+1

這不是一個答案;這是一個問題或建議,應作爲評論發佈。如果你想讓它成爲一個答案,你需要添加內容才能成爲一個答案,並將其作爲答案而不是問題。 –

+0

感謝您的評論。編輯。 –

+0

好吧,原來,在我開始使用臨時文件作爲互斥體之前,我嘗試過使用win全局互斥體,但是*如果我記得正確的*,有一些版本的窗口會出現問題。我使用的一些代碼是在Windows NT的時候寫的......如果我沒記錯的話,在某些帶有某些版本的Windows的機器上,全局互斥體不是全局的(至少我不能做到這一點)工作)...所以我決定使用文件。大概我應該給win32互斥體另一個嘗試? –

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. 

BTW完成:GetTempDir看起來是一個目錄,但是你把它作爲一個路徑。所以最好將其重命名爲GetTempPath而不是:o)

+0

謝謝,這是一個非常好的建議。在這種情況下,我必須記住,我仍然必須使用文件作爲互斥體。現在我正在測試TMutex,並且迄今爲止這麼好。 –