2011-02-08 198 views
1

我在4.0中使用FileSystemWatcher進行混淆。我覺得這非常有用,但我陷入了循環。我試圖監視每當一個ini被改變,並將其改回到正確的默認值(長篇故事),但改變事件複製到新文件導致它下降到一個循環...任何想法>?我玩弄了刪除和重新創建文件的想法,以避免觸發已更改的事件,但這導致了另一套我希望避免的程序問題。另外我想象我可以覆蓋文本,但這也帶來了同樣的問題。在此先感謝幫助FileSystemWatcher,取消訂閱事件

static void Main() { Watch (@"\\NoFault2010\Lexis\Data\Setup\", "tmconfig.ini", true); } 

     static void Watch (string path, string filter, bool includeSubDirs) 
     { 
      using (var watcher = new FileSystemWatcher (path, filter)) 
      { 

       watcher.Changed += FileChanged; 

       watcher.EnableRaisingEvents = true; 

       Console.WriteLine("Do Not Close ... \n\nThis is a Temporary Configuration Manager for Time Matters ... \n\n\nI'm Listening ............"); 
       Console.ReadLine(); 
      } 
     } 

    static void FileChanged (object o, FileSystemEventArgs e) 
    { 
     string _right_stuff = @"\\NOFAULT2010\Lexis\Data\Templates\Programs\tmconfig.ini"; 
     string _working = @"\\NOFAULT2010\Lexis\Data\Setup\tmconfig.ini"; 

     System.Threading.Thread.Sleep(2000); 

     File.Copy(_right_stuff, _working, true); 

     Console.WriteLine("File {0} has been {1}", e.FullPath, e.ChangeType); 
     MAIL_IT("[email protected]", "TM Master.INI has been altered", "Check the Master INI and Yell At Ecopy Guy " + e.ChangeType + e.FullPath); 

    } 

如何取消訂閱該事件以避免進入此循環。

回答

1

我寫這取決於FileSystemWatcher的應用程序 - 也,有時FSW處理程序進行了更改的文件。 我走近它在兩個方面 - 首先是拿我的代碼將是改變文件非常快的觀點 - 讓我做

fsw.EnableRaisingEvents = false; 
//make my change 
fsw.EnableRaisingEvents = true; 

不過,如果你覺得其他文件可能會期間得到改變時間,你可以記錄你進行更改的時間並將數據存儲在某處...

說,字典mapFileNameTimeChanged ...在這裏你可以存儲文件名...所以在你的處理程序中,你可以做類似....

fsw_Changed(object sender, FileSystemEventArgs e) 
{ 
    lock (m_mapFileNameChanged) 
    { 
     if (m_mapFileNameChanged.ContainsKey(e.FullPath)) 
     { 
      FileInfo fileInfo = new FileInfo(e.FullPath); 
      if (fileInfo.LastAccessTime == m_mapFileNameChanged[e.FullPath] 
      { 
       return;//not been changed since you last did something with it.... 
      } 
     } 
     else 
     { 
      m_mapFileNameChanged.Remove(e.FullPath);//discard this now..it has changed since you last looked at it...need to look at it again! 
     } 
    } 

    //do things in your event handler... 
    lock (m_mapFileNameChanged) 
    { 
     // copy or change the file here... 
     FileInfo fileInfo = new FileInfo(e.FullPath); 
     m_mapFileNameChanged[strFullPathToFile] = fileInfo.LastAccessTime; 
    } 
} 
0

你可以添加一個布爾值(再次在類級別),你可以用它來跟蹤是否該改變是由你造成的,如果是的話,就立刻退出,你FileChanged方法,即:

static bool inEdit; 
static void FileChanged (object o, FileSystemEventArgs e) 
{ 
    if (inEdit) 
     return; 
    inEdit = true; 

    // Do processing 

    inEdit = false; 
} 
+0

-0.5:有可能是比賽在這裏ŧ帽子會不起作用。如果交付活動有延遲(例如,他們排隊),然後更改事件將在FileChanged()退出後發佈(並且inEdit已返回false)。 – payne 2011-02-08 00:47:45

2

要當你與文件擺弄自己暫時禁用事件:

static void FileChanged (object o, FileSystemEventArgs e) 
{ 
    watcher.Changed -= FileChanged; 

    ... correct the file here... 

    watcher.Changed += FileChanged; 
} 

或者,您可以使用保護變量來檢測重入調用:

static bool reentrant = false; 
static void FileChanged (object o, FileSystemEventArgs e) 
{ 
    if (reentrant) 
     return; 

    reentrant = true; 

    ... correct the file here... 

    reentrant = false; 
} 

注意,你也想的方法或您的文件守望內完成的異常處理可以在出現問題時成爲終身的殘疾。

0

退訂是容易的,所以我不知道如果是這樣的問題:

watcher.Changed -= FileChanged 

另外,我想創造一些對象是SynchronizationObject的守望者。有一個問題,默認情況下,觀察者在新線程中引發事件,因此如果在創建新線程後取消訂閱,則可能會遇到問題。

也注意到,FileSystemWatcher的可能引發的東西多事件,你認爲是單一事件,它可能會影響你的程序的運作。

0

如果使監視器A類變量,而不是一個局部變量,那麼你的FileChanged方法應該能夠訪問它。那麼你應該能夠做到像

static void FileChanged (object o, FileSystemEventArgs e) 
{ 
    watcher.EnableRaisingEvents = false; 
    // Edit the file here 
    watcher.EnableRaisingEvents = true; 
}