2010-09-25 27 views
4

我正在創建一個使用FileSystemWatcher的Windows應用程序。 FileSystemWatcher監視一些目錄的變化。每次將某個文件添加到此目錄中時FileSystemWatcher都必須將此文件的信息添加到XML文件中。所有的工作都很好,但是當我在同一時間添加100個文件(例如某些應用程序將這些文件添加到目錄中)時,並不是每個文件的信息都出現在此xml文件中。FileSystemWatcher通知

我想使用隊列。並用它來添加項目到這個集合。並使用計時器。計時器將從這個集合中向XML添加信息。這是個好主意嗎?

任何人都可以告訴我該怎麼做?


所以我認爲我必須創建一個Windows應用程序和Windows服務。 WinApp只會將信息添加到EventLog,Windows Service將讀取EventLog信息並將其寫入XML。我認爲這將是最好的辦法。我在等待好的建議

+1

'FileSystemWatcher'被稱爲是對這類東西的挑剔。 – 2010-09-25 06:05:30

+0

所以你可以建議 – AEMLoviji 2010-09-25 06:13:16

+0

謝謝阿薩夫拉維。我知道我的英語不夠好。 – AEMLoviji 2010-09-25 07:58:42

回答

2

正如Michael Stum在他的回答中所寫,您可以嘗試增加緩衝區大小(FileSystemWatcher.InternalBufferSize)。但請注意,您不應將此值設置爲太高的值。另外,恕我直言,這可能只是一個臨時性的修復,請參閱當您同時向文件夾添加更多文件時發生的情況。

我看過一些其他的東西,你可以嘗試,如果增加緩衝區大小沒有幫助:

  • 如果您訂閱的FileSystemWatcher通知事件,儘量保持你的事件處理程序短可能;即。確保執行不會停留太久。如果你必須爲每個文件通知做相當數量的工作,你可以嘗試啓動一個單獨的線程並在那裏進行處理;您的事件處理程序可以很快返回調用方(並且文件通知將更快地從緩衝區/隊列中移除)。

  • 請勿使用由FileSystemWatcher提供的任何其他信息,除了基本通知有所變更外。一旦獲得任何文件更改通知,請等待一段時間,直到沒有更多通知到達(即等待100個同時文件更改通知中的最後一個通知)。然後手動列出目錄的內容並將所需信息傳輸到您的XML。

    這有一個主要缺點:手動檢測文件是否被刪除,重命名或創建是否不容易。你的程序將不得不保留最後一個目錄列表,根據這個目錄列表可以比較當前列表,找出發生了什麼變化。

    這樣做的好處是您可以相當確定,由於某些FileSystemWatcher緩衝區溢出,將不會丟失任何更改。

2

FileSystemWatcher有一個用於更改的內部緩衝區。當有很多快速更改時,緩衝區可能無法捕獲所有事件。

嘗試將InternalBufferSize增大到更高的值。

您可以將緩衝區設置爲4 KB或更大,但不得超過64 KB。爲獲得最佳性能,請在基於Intel的計算機上使用4 KB的倍數。

系統通知組件文件更改,並將這些更改存儲在組件創建並傳遞到API的緩衝區中。每個事件最多可以使用16個字節的內存,不包括文件名。如果短時間內有很多變化,緩衝區可能會溢出。這會導致組件無法跟蹤目錄中的更改,並且只會提供一攬子通知。增加緩衝區的大小具有以下分支:

增加緩衝區大小可以防止丟失文件系統更改事件。請注意,由於Windows操作系統的依賴關係,FileSystemWatcher類的一個實例可能在事件丟失或超出緩衝區大小時引發錯誤事件。

增加緩衝區的大小非常昂貴,因爲它來自不能換出到磁盤的非分頁內存,因此請儘可能減小緩衝區。爲避免緩衝區溢出,請使用NotifyFilter和IncludeSubdirectories屬性來過濾不需要的更改通知。

對於診斷,也許您應該先訂閱Error Event以查看它是否確實是緩衝區溢出。

同樣如上所述,將NotifyFilter設置爲所需的最小標誌,如果您只想跟蹤更改,則可能爲NotifyFilters.LastWrite

+0

謝謝我會測試它 – AEMLoviji 2010-09-25 06:20:19

1

如果我理解正確的話:你看目錄,並在許多文件在同一時間得到補充你只看到其中的一些與FileSystemWatcher

你有沒有試過如下:在OnCreated事件處理程序,只要到文件系統,並取得相應目錄的完整內容,不管是什麼情況告訴你?

+0

是的,這是個好主意。但在XML文件必須數據保存爲:<?XML版本= 「1.0」 編碼= 「UTF-8」> 952063 \ ETIden \ filename.xls 23分之9/ 2010上午11點30分03秒 952063 \ ETIden \ 952063.rar 2010年9月23日上午11點30分03秒 刪除0和deleted1(表示文件952063 \ ETIden \ filename.xls已添加,但952063 \ ETIden \ 952063.rar已刪除) – AEMLoviji 2010-09-25 06:17:14

+0

因此,XML文件實際上是文件系統更改日誌。 – Reinderien 2010-09-25 06:20:26

+0

當然可以。在這個XML文件中,所有的日誌都保存了 – AEMLoviji 2010-09-25 06:53:04

2

有一個在MSDN文檔,可以幫助您更可靠地檢測變化的關鍵注:

保持你的事件處理代碼的短 越好。

我懷疑(但不知道肯定),這是因爲文件系統事件在主線程觀察家提出,讓您花處理事件的任何時間創建了一個窗口,其中的變化可以不被發現。您描述解決方案的方式似乎是您在回調中執行I/O(寫入您的XML更改日誌文件),並且根據API中的條件,執行內聯工作肯定會有太多工作要做文檔。如果您有很多工作要做,請將事件交給另一個線程進行處理,以便您儘快恢復觀看文件系統。

一個相對簡單的方法是使用ThreadPool.QueueUserWorkItem。這意味着您的更改日誌仍然不會與文件系統的狀態同步100%(由於使用單獨的線程和隊列引入了延遲),但它可能更準確,這似乎是您最關心的問題。您需要確保線程池調用的WaitCallback是線程安全的(例如,如果沒有lock()或類似文件,寫入更改日誌不會同時發生),並且請注意,無法保證將更改日誌條目寫入他們發生的順序(儘管我懷疑FileSystemWatcher是否可以保證)。

每對API的指導方針

而且 - 確保您過濾可能的事件集,只讓叫回那些你絕對必須看到:

爲了避免緩衝區溢出,使用NotifyFilterIncludeSubdirectories properties因此,您可以過濾掉 不需要的更改通知。