2010-03-05 108 views
1

我目前工作的一個文件處理服務,着眼於文件共享,在文件通過FTP上傳到。共享文件鎖

在可擴展性,我被要求作出這項服務能夠進行負載平衡,因此該服務有期待,在不同機器上的其他服務也可能試圖處理這些文件。

OK,所以我想我應該能夠處理文件之前得到我的過程中獨佔鎖,並跳過可能已經被其他進程鎖定任何文件實現這一目標。

這種方法的關鍵如下所示(我已經離開了錯誤處理的簡單):

using(FileStream fs = File.Open(myFile, FileMode.Open, FileAccess.ReadWrite, (FileShare.Read | FileShare.Delete)) 
{ 
//Do work 
} 

Q1:我的過程,現在對這個文件的鎖。我認爲這將意味着我可以訪問相同的文件(不使用流)並仍然具有正確的訪問權限,但基於測試,似乎我只具有通過流鎖定的好處。它是否正確?

(例如,之前我包括FileShare.Delete,File.Delete(MYFILE)失敗)

上面鎖最終使用的「寫入」權限,以確定哪些服務具有的文件,而是意在允許其他進程仍然讀取文件。這是因爲具有該鎖的進程嘗試驗證該文件是否是使用第三方庫(Xceed.Zip)的有效zip文件。但是,這沒有說明文件「正在被另一個進程使用」。使用反射我終於找到了問題的電話是:

stream = this.m_info.Open(FileMode.Open, FileAccess.Read, FileShare.Read); 

現在我本來期望這個工作,因爲它只是想要閱讀該文件,但它失敗。原因似乎在similar question中概述。但是,由於這是第三方API,我無法將其代碼更改爲使用ReadWrite。

Q2:有沒有一種方法可以正確鎖定文件,使其不會被其他服務佔用,但仍可以使用外部API將其驗證爲zip文件?

我覺得應該有一個'正確'的方法來做到這一點,但目前我能做到的最好的辦法是鎖定文件,將它從共享目錄移開,然後在新的位置。

回答

0

如果你打算通過處理UnauthorizedAccessException我認爲你正在犯一個嚴重的錯誤被動地處理這種情況。

這可以通過主動重命名文件來處理。例如,您可以將服務配置爲僅讀取名稱格式爲「Filename.YYYYMMDD.txt」的文件。在處理文件之前,您可以將其重命名爲'Filename.YYYYMMDD.processing'。然後在處理文件後,將其重命名爲'Filename.YYYYMMDD.done'。

你甚至可以把它更進一步,使該入隊的另一名服務。該服務將是一個FileSystemWatcher,用於偵聽FileAdd操作。一旦收到該事件,它就會將文件名排隊到全局消息隊列。然後,您的每個服務都將僅僅是取消文件名,而不再需要擔心併發訪問。

HTH

+0

接受爲替代解決方案是合理的。回答我自己的問題: 問題1:是的。鎖僅用於流,而不是流程 Q2:否。必須考慮替代方案。 – MattH 2010-04-23 10:39:46