FileSystemWatcher,取消订阅该事件

时间:2011-02-08 00:35:36

标签: c#

我在使用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);

    }

如何取消订阅活动以避免进入此循环。

5 个答案:

答案 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;
}