2011-02-18 85 views
4

我有一個文本文件,多個線程/進程將寫入它(它是一個日誌文件)。在文件系統級同步寫入文件

由於併發寫入,文件有時會損壞。

我想使用文件系統級自身的所有線程的文件寫入模式。

我知道可以使用鎖(多進程互斥鎖)並同步寫入此文件,但我更願意以正確的模式打開文件並將任務保留到System.IO

可能嗎?這種情況下的最佳做法是什麼?

+0

所有的進程是在同一臺機器上運行,還是在訪問網絡共享上的文件? – 2011-02-18 18:46:33

+0

我不認爲(但我不是100%肯定)有一種方法可以在「等待它可以鎖定」類型的共享模式下打開文件。我認爲唯一能做到你想做的就是使用互斥體。當然,如果你在網絡共享上打開一個文件,那也不是解決方案,你可能需要設置一個服務器來接受日誌調用。 – 2011-02-18 18:47:31

+0

@Lasse:同一臺機器上的所有線程/進程(windows) – Xaqron 2011-02-18 18:58:51

回答

1

您可以使用File.Open(),將FileShare的值設置爲None,並使每個線程等待(如果它無法訪問該文件)。

+0

我認爲這將導致訪問異常,除非有阻塞調用或等待句柄。 – Xaqron 2011-02-18 18:44:16

3

最好的辦法就是使用鎖/ mutexex。這是一個簡單的方法,它的工作原理,你可以很容易地理解它並推理它。

當涉及到同步時,它通常會從最簡單的解決方案開始,並且只有在遇到問題時纔會嘗試優化。

2

據我所知,Windows沒有你要找的東西。沒有文件句柄對象通過在寫入文件時阻止所有其他用戶來進行自動同步。

如果你的日誌涉及三個步驟,打開文件,寫,關閉文件,然後你可以有你的線程試圖在獨佔模式(FileShare.None)打開該文件,如果無法打開,捕獲異常,然後再試一次直到成功。我發現最好的是乏味。

在我從多個線程登錄的程序中,我創建了一個基本上是隊列的後代。線程調用該對象上的WriteWriteLine方法,該方法將輸出格式化並放入隊列中(使用BlockingCollection)。單獨的日誌記錄線程爲該隊列提供服務 - 從中​​抽取事件並將它們寫入日誌文件。這有幾個好處:

  • 線程不必爲了登錄
  • 只有一個線程在相互等待被寫入文件
  • 是微不足道的旋轉日誌(即啓動一個新的記錄每一個小時文件等)
  • 有一個錯誤的機率爲零,因爲我忘了做一些螺紋

這樣做跨進程將是一個更加困難的鎖定。我從來沒有考慮過跨進程共享日誌文件。如果我需要,我會創建一個單獨的應用程序(一個日誌服務)。該應用程序將執行實際寫入操作,其他應用程序傳遞字符串以進行寫入。同樣,這可以確保我不能搞砸,而且我的代碼仍然很簡單(即客戶端沒有顯式鎖定代碼)。