2012-02-22 29 views
0

我想實現一個文件觀察器,如果文件內容被更改,將引發一個事件。 一旦我正在觀看的文件被修改,我得到2個事件的問題。 (我想它只有一次)FileSystemWatcher得到太多的事件

_automationStatusWatcher = new FileSystemWatcher(fileInfo.Directory.FullName, 
               fileInfo.Name); 
_automationStatusWatcher.NotifyFilter = NotifyFilters.LastWrite; 
_automationStatusWatcher.Changed += OnAutomationStatusChanged; 
_automationStatusWatcher.EnableRaisingEvents = true; 

,我是看不打算重新創建文件/移動/刪除/不管。它的目的是成爲一個xml數據庫文件,我需要監視它一旦發生變化。我想在文件被修改時僅獲得1個事件並忽略其他事件。

我該怎麼做?

+1

胎面2個非常接近事件爲一體...這就是我目前的解決方案。 – Bolu 2012-02-22 14:30:50

回答

2

Manual

注意

常見的文件系統操作可能會引發多個事件。例如,當文件從一個目錄移動到另一個目錄時,可能會引發幾個OnChanged和一些OnCreated和OnDeleted事件。移動文件是一項複雜的操作,由多個簡單操作組成,因此引發多個事件。同樣,某些應用程序(例如防病毒軟件)可能會導致由FileSystemWatcher檢測到的其他文件系統事件。

+0

我明白這一點,但是有沒有特定的事件來檢查文件是否被修改?此文件無意移動到其他文件夾或正在創建。 – user829174 2012-02-22 14:28:12

+0

不知道你應該-1他的答案,你沒有指定任何你想知道的。 「我該怎麼做呢?」是一個可怕的問題。 – dsingleton 2012-02-22 14:30:49

+0

@ user829174你的問題不清楚。正如手冊所述,多種事件可以在各種場合引發。如果你想得到有用的答案,請發佈可複製的測試用例。何時發生多個事件,何時只需寫入文件?或者你在移動文件?你有沒有運行病毒掃描程序? – CodeCaster 2012-02-22 14:31:49

0

如果你看看FileSystemWatcher的文檔,它說它會多次觸發。

Moving a file is a complex operation that consists of multiple simple operations, therefore raising multiple events. Likewise, some applications (for example, antivirus software) might cause additional file system events that are detected by FileSystemWatcher. 

我會建議做某種類型的排隊機制,使您不必在同一文件的多個動作。

1

你可以嘗試解開事件處理程序,一旦你發現一個變化,直到你準備好接受更多的變化:

​​

但是,這不一定是線程安全的,你可以得到多次點火反正。 另一種選擇是使用一個信號變量,看看你正在處理的變化:

private bool _inStatusChange = false; 
private void OnAutomationStatusChanged(object sender, args...) 
{ 
    if (_inStatusChange) 
    { 
     return; 
    } 
    else 
    { 
     _inStatusChange = true; 
     //do work 
     _inStatusChange = false; 

    } 
} 

你應該用適當的鎖定,以保持接入信號變量線程安全的。

2

前段時間我不得不應付這個問題。我想在創建文件時收到通知。問題在於當文件仍然是空的或仍在寫入時觸發事件,而不是在新文件關閉時觸發。

解決方案是使用臨時名稱創建文件,並在完成將文件重命名爲其最終名稱後創建該文件。然後,我觀看了重命名事件。

您可以在寫入文件時將文件命名爲myfile.tmp,完成後將其重命名爲myfile.xml並觀看重命名事件。

0

我有一個類似的問題來檢查日誌記錄配置中的更新。
我讀了關於FileSystemWatcher的多重事件問題。所以我決定實施另一種解決方案。

我檢查配置文件的每個訪問權限,如果它通過比較修改日期進行了更改。後來我添加了一個延遲(2秒)以避免對文件系統的訪問過多。也許你也可以用那種方式。

0

我遇到這個問題太大,現在我發現這種方式:

new Thread(() => { 
      while (true) { 
       var r = watch.WaitForChanged(WatcherChangeTypes.All); 
       this.Invoke(new ThreadStart(() => { 
        listBox1.Items.Add(string.Format("{0} {1} {2}", DateTime.Now, r.Name, r.ChangeType)); 
       })); 
      } 
     }) { IsBackground = true }.Start(); 

它非常類似於NIO在Java中