我在使用4.0中的FileSystemWatcher。我发现这非常有用,但我陷入了困境。我试图监视每次更改ini并将其更改回正确的默认值(长篇故事),但是复制新文件的更改事件会导致它进入循环...任何想法> ?我玩弄了删除和重新创建文件的想法,以避免触发更改的事件,但这会导致程序的另一组问题,我宁愿避免。此外,我想我可以覆盖文本,但这也会带来同样的问题。在此先感谢您的帮助
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("SQLMail@lcjlawfirm.com", "TM Master.INI has been altered", "Check the Master INI and Yell At Ecopy Guy " + e.ChangeType + e.FullPath);
}
如何取消订阅活动以避免进入此循环。
答案 0 :(得分: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;
}
请注意,您还需要在方法中执行异常处理,否则如果出现问题,您的文件观察程序可能会永久禁用。
答案 1 :(得分: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;
}
}
答案 2 :(得分:0)
您可以添加一个布尔值(同样在类级别),用于跟踪更改是否由您引起,如果是,则立即退出FileChanged方法,即:
static bool inEdit;
static void FileChanged (object o, FileSystemEventArgs e)
{
if (inEdit)
return;
inEdit = true;
// Do processing
inEdit = false;
}
答案 3 :(得分:0)
取消订阅很容易,所以我想知道这是不是问题:
watcher.Changed -= FileChanged
另外,我会为观察者创建一些对象作为SynchronizationObject。存在一个问题,默认情况下,观察者会在新线程中引发事件,因此如果在创建新线程后取消订阅,则可能会遇到问题。
另外值得注意的是,FileSystemWatcher可能会为您认为是单个事件的事件引发多个事件,并且可能会影响您的程序的运行。
答案 4 :(得分:0)
如果您使观察者成为类变量而不是局部变量,那么您的FileChanged方法应该能够访问它。然后你应该能够做类似
的事情static void FileChanged (object o, FileSystemEventArgs e)
{
watcher.EnableRaisingEvents = false;
// Edit the file here
watcher.EnableRaisingEvents = true;
}