C# FileSystemWatcher,取消订阅事件

C# FileSystemWatcher,取消订阅事件,c#,C#,我在和4.0中的FileSystemWatcher鬼混。我觉得这很有用,但我陷入了一个循环。我试图监视ini的任何更改,并将其更改回正确的默认值(说来话长),但是,在新文件上复制更改事件会导致它陷入循环。。。有什么想法吗?我反复考虑删除并重新创建文件以避免触发已更改的事件,但这会导致程序出现另一系列问题,我宁愿避免。我还想象我可以改写文本,但这也带来了同样的问题。提前谢谢你的帮助 static void Main() { Watch (@"\\NoFault2010\Lexis\Data\S

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

    }
如何取消订阅事件以避免进入此循环。

您可以添加一个布尔值(同样是在类级别),用于跟踪更改是否由您引起,如果是,请立即退出FileChanged方法,即:

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

    // Do processing

    inEdit = false;
}

要在自己处理文件时临时禁用事件,请执行以下操作:

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

    ... correct the file here...

    watcher.Changed += FileChanged; 
}
或者,您可以使用guard变量检测可重入调用:

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

    reentrant = true;

    ... correct the file here...

    reentrant = false;
}

请注意,您还需要在该方法中执行异常处理,否则如果出现问题,您的文件监视程序可能会永久禁用。

取消订阅很容易,因此我想知道这是否是问题所在:

watcher.Changed -= FileChanged
另外,我将创建一些对象作为观察者的SynchronizationObject。默认情况下,watcher会在新线程中引发事件,因此,如果在创建新线程后取消订阅,则可能会遇到问题


还注意到,FraseSistMeaveCurter可能会为你认为是单个事件的事件引发多个事件,并且可能影响程序的运行。

如果使观察者成为类变量而不是局部变量,那么您的文件更改方法应该能够访问它。那么你应该可以做一些类似的事情

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

我已经编写了一个依赖于filesystemwatcher的应用程序,而且有时候fsw处理程序会对文件进行更改。 我用两种方法来处理它——第一种是认为我的代码在更改文件时会非常快——所以我这么做了

fsw.EnableRaisingEvents = false; 
//make my change
fsw.EnableRaisingEvents = true; 
但是,如果您觉得其他文件可能在这段时间内发生更改,您可以记录更改的时间并将数据存储在某个位置

比如说,Dictionary 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.5:这里可能会有一场比赛,这将使比赛无法进行。如果在传递事件时出现延迟(例如,事件已排队),则更改事件将在FileChanged()退出后发布(并且inEdit已返回false)。