-1

背景FileSystemWatcher的報告可用的文件網絡共享,但文件無法找到

我有了一個共享文件夾\\Server\Share有4子文件夾的服務器:

  • OutboundFinal
  • OutboundStaging
  • InboundFinal
  • InboundStaging

所有文件夾駐留在同一個物理磁盤和分區上,不使用連接點。

我也有幾個WinForms客戶端(最多10個)寫和讀文件到這個共享中,每個客戶端在多線程(最多5個)上工作。客戶端文件(最多50個線程)被登錄到\\Server\Share\OutboundStaging文件夾中。每個文件都有一個GUID的名稱,所以不會覆蓋。文件完成寫入後,客戶端將其移至\\Server\Share\OutboundFinal文件夾。在同一臺服務器上運行的Windows服務會將其選中,刪除,處理,然後將具有相同名稱的文件寫入\\Server\Share\InboundStaging文件夾。文件完成寫入後,它將被服務移動到\\Server\Share\InboundFinal文件夾。

這\\服務器\共享\文件夾InboundFinal通過使用FileSystemWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut);FileSystemWatcher.Filter每個客戶的WinForms每個線程監視設置爲某線程預計在\服務器\共享查看該文件的文件名GUID \ InboundFinal文件夾,因此FileSystemWatcher會一直等到文件夾中顯示特定文件。

我已經閱讀了關於FileSystemWatcher的幾個SO問題,表現不正常並且未報告UNC股份的變化。然而,這不是我的情況。

我使用的代碼如下所示:

FileSystemWatcher fileWatcher = new FileSystemWatcher(); 
    fileWatcher.Path = InboundFinalFolder; 
    fileWatcher.Filter = GUIDFileName; // contains full UNC path AND the file name 
    fileWatcher.EnableRaisingEvents = true; 
    fileWatcher.IncludeSubdirectories = false; 
    var res = fileWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut); 
    if (!fileWatcher.TimedOut) 
    { 
     using (FileStream stream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) { 
     byte[] res = new byte[stream.Length]; 
     stream.Read(res, 0, stream.Length); 
     return res; 
    } 

這是使用行拋出異常。

的問題

我將認爲fileWatcher.WaitForChanged將繼續只要用正確的GUID名的文件在\\Server\Share\InboundFinal文件夾中。這正是FileSystemWatcher在本地文件夾上的工作方式,而不是通過網絡訪問的文件共享(本地文件,甚至通過共享訪問,也傾向於工作)。 FileSystemWatcher報告線程正在等待的文件位於FileSystemWatcher \\Server\Share\InboundFinal文件夾中。但是,當我嘗試讀取文件時,出現FileNotFoundException。讀取線程必須等待3-15秒才能讀取文件。我嘗試用FileStream與Read共享打開文件。

什麼可能導致此行爲?我如何解決它?理想情況下,FileSystemWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut);應該只能繼續執行,如果文件可以被讀取或超時發生。

+0

FileNotFoundException是非常基本的。一個標準的錯誤是使用GUIDFileName打開文件。不夠好,這不是一個完整的路徑。測試時意外工作,從不在服務器上工作。也可以嘗試禁用反惡意軟件,以防萬一它認爲在掃描時隱藏文件是個好主意。你沒有發佈實際失敗的代碼,所以這些只是猜測。 –

+0

GUIDFileName屬性包含完整的UNC路徑和GUID文件名。對不起,我編輯了我的問題中的代碼片段來澄清。 – Daniel

+0

這是**使用**行引發異常。 – Daniel

回答

0

的FileSystemWatcher的有一個不好的名聲,但實際上,它並不壞......

1。)

您的代碼示例不能編譯。我試過這個:

FileSystemWatcher fileWatcher = new FileSystemWatcher(); 
fileWatcher.Path = "X:\\temp"; 
fileWatcher.Filter = "test.txt"; 
fileWatcher.EnableRaisingEvents = true; 
fileWatcher.IncludeSubdirectories = false; 

var res = fileWatcher.WaitForChanged(WatcherChangeTypes.Changed | 
           WatcherChangeTypes.Created, 20000); 
if (!res.TimedOut) 
{ 
    FileInfo fi = new FileInfo(Path.Combine(fileWatcher.Path, res.Name)); 

    using (FileStream stream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) 
    { 
     byte[] buf = new byte[stream.Length]; 

     stream.Read(buf, 0, (int)stream.Length); 
    } 

    Console.WriteLine("read ok"); 
} 
else 
{ 
    Console.WriteLine("time out"); 
} 

我測試了這個,其中X:是一個SMB共享。它的工作沒有問題(對我來說,見下文)。

但是:

你應該打開/讀取重試(後,每失敗露宿100毫秒)的文件。這是因爲您可能會遇到FileSystemWatcher檢測到文件但移動(或其他寫入操作)尚未結束的情況,因此您必須等到文件創建/移動器真正準備就緒。

或者您不要等待「真實」文件,而是關閉文件移動任務在關閉「真實」文件後創建的標誌文件。

2)

難道說,此舉任務沒有正確關閉文件?

3)

幾年前,我有一些工具(用Perl編寫),其中一個腳本創建一個標誌文件,另一個腳本等待它。

我在SMB 2份額上遇到了一些令人討厭的問題。我發現這是由於SMB緩存。

https://bogner.sh/2014/10/how-to-disable-smb-client-side-caching/

File open fails initially when trying to open a file located on a win2k8 share but eventually can succeeed

https://technet.microsoft.com/en-us/library/ff686200.aspx

試試這個(在客戶端上):

Windows Registry Editor Version 5.00 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanWorkstation\Parameters] 

"DirectoryCacheLifetime"=dword:00000000 
"FileNotFoundCacheLifetime"=dword:00000000 

保存此作爲disablecache.reg和運行regedit disablecac he.reg

然後重新啓動。

+0

我不知道爲什麼它被投票(我固定),因爲你的答案有很多有用的信息我的情況。事實上,這個答案有許多與我的問題有關的事情。 – Daniel

+0

感謝您的回答。該FileNotFoundCacheLifetime設置似乎只是我需要的。我打開帶有重試次數的文件(重試10次,延遲1000毫秒,因爲它對我來說並不重要),但有時甚至還不夠。我忽略了那部分代碼,因爲它看起來不相關。 – Daniel