2010-11-29 86 views
5

我可以使用FileStream構造函數來確保一次只有一個進程訪問文件嗎?下面的代碼會起作用嗎?我可以使用FileStream來實現文件鎖嗎?

public static IDisposable AcquireFileLock() { 
    IDisposable lockObj; 
    do { 
     // spinlock - continually try to open the file until we succeed 
     lockObj = TryOpenLockFile(); 

     // sleep for a little bit to let someone else have a go if we fail 
     if (lockObj == null) Thread.Sleep(100); 
    } 
    while (lockObj == null); 

    return lockObj; 
} 

private static FileStream TryOpenLockFile() { 
    try { 
     return new FileStream(s_LockFileName, FileMode.Create, FileAccess.Read, FileShare.None); 
    } 
    catch (IOException) { 
     return null; 
    } 
} 

特別是與FileMode.Create原子WRT其他進程的行爲?有什麼我應該使用?

編輯:更具體地說,這是Microsoft CLR在單個機器上使用本地文件。

+0

這看起來不錯!誰清理鎖文件?由於`FileStream``ctor調用總是覆蓋現有的鎖定文件,因此可能沒有功能需要這麼做。 – 2010-11-29 18:17:38

+0

對於清理,我總是可以`嘗試{File.Delete(...)}`並忽略任何異常(因爲這意味着另一個進程在此期間進行了鎖定)... – thecoop 2010-11-29 18:24:42

回答

2

這將做你想做的。 FileShare.None是重要組成部分。

如果所有的作家應用程序是在同一臺計算機上,你也可以使用一個named Mutex來達到同樣的目標,而不需要一個物理文件,或以調解文件的訪問,如果你不關心誰寫入到文件的最後(只是寫入不是併發的)。這可以使您不必每次重新打開該文件,而是提供阻塞語義,而不是您的Sleep循環(更好的perf)。

請注意,如果名稱不被視爲祕密,即需要保持安全的信息,任何進程都可以蹲在您的文件(Mutex)上。

+2

Mutex只能用於相同電腦。文件鎖在網絡上工作。 – Gabe 2010-11-29 18:06:39

1

這將工作,因爲要注意以下幾點:

  • 您使用的是Windows(在Linux上通過單聲道,這是站不住腳的,因爲文件鎖是諮詢,所以你的方法總是成功)
  • 您正在訪問本地文件(SMB也可能會工作,但NFS或WebDAV幾乎可以肯定不會)
  • 捕獲IOException異常可能是過於寬泛,您需要專門驗證它失敗,因爲共享衝突的