2010-07-14 106 views
13

我正在編寫一個監視網絡目錄並運行在Windows Server 2008計算機上的工具,FileSystemWatcher的OnChanged事件正在從位於網絡驅動器上的任何計算機不使用Windows 7,出於某種原因,如果在Windows 7計算機上覆制的文件數量超過19個(一次),則不會觸發任何事件,儘管它在個別完成文件時有效。有沒有解決方法,或者是Windows 7內核如何處理FSW事件?FileSystemWatcher和Windows 7

只是爲了澄清它從XP機器複製時可用於成千上萬的文件。 (該軟件仍然在2008年的服務器上)。

回答

22

MSDN

Windows操作系統在通知由FileSystemWatcher的創建一個緩衝的文件更改的組件。如果短時間內有很多變化,緩衝區可能會溢出。這會導致組件無法跟蹤目錄中的更改,並且只會提供一攬子通知。使用InternalBufferSize屬性來增加緩衝區的大小非常昂貴,因爲它來自無法換出到磁盤的非分頁內存,所以請將緩衝區保持爲小但足夠大以便不會錯過任何文件更改事件。爲避免緩衝區溢出,請使用NotifyFilterIncludeSubdirectories屬性,以便過濾掉不需要的更改通知。

如果增加緩衝區大小不夠,並且無法控制一次觸發事件的數量,則必須添加其他輪詢。

又見此相關的問題:

FileSystemWatcher does not work properly when many files are added to the directory at the same time…

更新:

這可能是很有誘惑力的簡單增加緩衝區的大小,但是這應該格外小心。實際上,在網絡訪問方面存在64k的限制。所述FileSystemWatcher類使用Windows API函數ReadDirectoryChangesW下方具有這種限制:

ReadDirectoryChangesW失敗ERROR_INVALID_PARAMETER當緩衝長度是大於64 KB,並且應用程序在網絡上監視的目錄。這是由於底層文件共享協議的數據包大小限制。

如果你想獲得關於修改緩衝區大小的成本更深入的瞭解,你應該看看微軟的沃爾特·王在這裏的職位:

FileSystemWatcher across the network(滿郵報以下)

我很抱歉, FileSystemWatcher.InternalBufferSize 的文件沒有說明有關監視網絡當 緩衝區的大小很清楚路徑。監測網絡路徑時建議不要超過64K 。

FileSystemWatcher基本上是一個。Net Win32的封裝器 ReadDirectoryChangesW API。要使用 ReadDirectoryChangesW,您創建並且 指定一個緩衝區,操作系統將使用這些更改填充 。然而, 什麼不 ReadDirectoryChangesW文件 中提到的(但在 FileSystemWatcher的文檔被暗示)是, 文件系統創建一個內部的內核 緩衝存儲的變化信息 暫時直到它有機會 更新用戶緩衝區。 的大小創建的內核緩衝區是 ,其大小與在 ReadDirectoryChangesW中指定的大小相同,並在非分頁池化內存中創建爲 。每創建一個FileSystemWatcher/ ReadDirectoryChangesW創建/ 調用,新的內核緩衝區也創建爲 。

內核存儲器池(分頁和 非分頁)在設備驅動程序和 使用其他內核組件系統 地址空間預留。他們 成長和收縮動態作爲 必要的。 管理器的「性能」選項卡上的 可輕鬆看到當前池的大小。這些池將動態增長 ,直到它們達到最大值 的值,該值在引導時間 處計算,並且取決於可用的系統資源(主要是RAM) 資源。你不要 想要達到這個最大值,否則 各種系統服務和驅動程序 將開始失敗。但是,這個 計算最大值不容易 可用。要確定池的最大大小,您需要使用內核 調試器。如果您對 有關係統 內存池的進一步信息感興趣,我建議您參考Moscress book 第7章中的第7章Solomon和 Russinovich。

考慮到這一點,沒有 推薦您可以使用什麼樣的大小緩衝區 。系統池的當前和最大尺寸將根據客戶的不同而不同,分別爲 。 但是,對於每個FileSystemWatcher/ ReadDirectoryChangesW緩衝區,您可能不應該使用 。 源於網絡訪問64k的限制 在ReadDirectoryChangesW中記錄的事實。 但最終你將有 測試預期目標系統的各種 的應用程序,以便您可以調整您的緩衝區 。

還有就是開銷與.net 應用相關的,我認爲一個 的Win32 ReadDirectoryChangesW程序 可能能夠達到更好的性能 用相同的緩衝區大小。 然而,隨着速度非常快,許多 文件的變化,緩衝區溢出將 不可避免的,開發商會 不得不處理的情況下發生 超限如手動 枚舉目錄檢測 的變化。

總之,FileSystemWatcher的和 ReadDirectoryChangesW是 輕量級的文件變化檢測 機制,都將有其侷限性 。更改日誌是 另一種機制,我們將 考慮一箇中等重量的解決方案,但 仍然有侷限性:

http://msdn.microsoft.com/en-us/library/aa363798%28VS.85%29.aspx

重量級的解決方案將是 寫一個專用的文件系統過濾 驅動程序坐在文件系統 堆棧和監視文件系統 的變化。當然這將是最複雜的方法。大多數病毒 掃描程序,備份軟件和文件 系統監控實用程序,如 的Filemon(www.sysinternals.com) 實現一個篩選器驅動程序。

我希望以上說明可以幫助您瞭解 您遇到的問題的根本原因 。請回復 讓我們知道您是否需要 更多信息。謝謝。

+0

只需加入少量的:默認的緩衝區大小爲8192 – 2011-09-29 08:46:34

4

經過很多次使用FileSystemWatcher的嘗試後,我放棄了它。它不會在錯誤的時間正確地觸發事件,錯誤的類型。老實說,我認爲這是.NET框架中最糟糕的類之一。我總是最終編寫自己的需要System.Timer的類,經過x毫秒後,它會手動檢查目錄和文件。是的,它需要更多的工作,是的,它可以是一個輕微的PITA,但一旦你寫了它,你可以在任何你想要的地方使用它。我希望FileSystemWatcher像廣告一樣工作,但我從來沒有發現它這樣做。

+0

我同意'FileSystemWatcher'顯然不是適用於所有情況。然而,它提供的一個功能很難用簡單的目錄枚舉來檢測文件重命名。它可以完成(使用文件屬性比較,啓發式,MD5總和等),但這很麻煩。 – stakx 2010-07-14 22:22:21

+0

@stakx,這是非常真實的,我從來沒有試圖檢查文件名稱的變化。我剛被那個班燒掉了,我從來沒有用過它。 – Justin 2010-08-02 21:40:30

2

大部分的時間,當FileSystemWatcher的事件觸發,我忽略了正在被傳遞的對象,因爲這個名單可能是不完整的文件。

我只是通過了FileSystemWatcher的對象監控目錄抓取和執行手動掃描以查找可能無法在FileSystemWatcher的緩衝區中的文件。這不是很高雅,但它確保你不會錯過一個文件。

+0

,這似乎是與OP所討論的不一致性完全分開的問題。 – Chad 2010-07-14 21:37:24

+0

@查德:看起來這完全不相關?我想說這聽起來就像是解決OP問題的方法。 – 2010-07-14 21:52:43

+0

,因爲OP說事件根本不會觸發。勞倫斯建議*當事件發生時*他們手動檢查目錄,但如果事件從不首先發生,OP不能做到這一點。因此,Laurens的評論並不是關於OP所看到的同樣的問題。至少,這就是我閱讀OP關於Laurens評論的問題。 – Chad 2010-07-15 00:45:44

0

這是一個真正可靠的階級,當文件超過一定閾值的我已經對事件的初始副本發射約7倍,然後在文件傳輸對話框做我得到另7個事件,這個問題似乎跨越所有支持FSW的操作系統。儘管Windows 7(尚未嘗試vista)仍然只能逐個接受文件,或者一次只接受19個文件,而如果我從XP機器中將文件放入網絡驅動器,我可以一次讀取數千個文件,而無需任何問題。這可能只是將ReadDirectoryChangesW從XP更改爲7.過去的19個文件無法獲取任何要觸發的事件,所以我想現在將成爲我的工具的「特性」。如果任何人有任何其他信息可以隨意貢獻。

-1

如果你使用Mac OS X +的Parallels Desktop + Windows中, 您的代碼不工作, 因爲你FileSystemWatcher.Path財產爲目標的MAC路徑,它是一個UNC路徑,它不支持!

enter image description here