2011-02-08 200 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; 
}