如何同步FileSystemWatcher

时间:2012-03-01 14:32:48

标签: c# multithreading

我有这段代码 我想在插件的StartWatch()和OnFinalChanged()之间进行同步,因此最终打印的内容将按以下顺序进行:

Creating plugin for file c:\temp\file1.txt
Creating plugin for file c:\temp\file2.txt
Creating plugin for file c:\temp\file3.txt
Starting watching c:\temp\file1.txt
Finished watching file c:\temp\file1.txt
Starting watching c:\temp\file2.txt
Finished watching file c:\temp\file2.txt
Starting watching c:\temp\file3.txt
Finished watching file c:\temp\file3.txt
namespace Test2
{
    internal static class MyProgram
    {
        [STAThread]
        private static void Main(string[] args)
        {
            List<Plugin> plugins = new List<Plugin>
                                       {
                                           new Plugin(@"c:\temp\file1.txt"),
                                           new Plugin(@"c:\temp\file2.txt"),
                                           new Plugin(@"c:\temp\file3.txt"),
                                       };

            foreach (var plugin in plugins)
            {
                // I need StartWatch to be called only after i got OnChanged() for the previous plugin
                plugin.StartWatch();
            }
        }
    }


    public class Plugin
    {
        private FileSystemWatcher _watcher;
        private readonly string _file;

        public Plugin(string file)
        {
            _file = file;
            Console.WriteLine("Creating plugin for file {0}", _file);
        }

        public void StartWatch()
        {
            Console.WriteLine("Starting watching {0}", _file);
            FileInfo fileInfo = new FileInfo(_file);
            if (fileInfo.Directory != null)
            {
                _watcher = new FileSystemWatcher(fileInfo.Directory.FullName, fileInfo.Name);
                _watcher.NotifyFilter = NotifyFilters.LastWrite;
                _watcher.Changed += OnChanged;
                _watcher.EnableRaisingEvents = true;
            }
            // i want the main thread to be paused untill i get the OnChanged()
        }

        private void OnChanged(object source, FileSystemEventArgs e)
        {
            Console.WriteLine("Finished watching file {0}", _file);
            _watcher.Dispose();

            // once i get this event, i want the main thread to continue and to start watching the same plugin
        }
    }
}

1 个答案:

答案 0 :(得分:2)

使用AutoResetEvent可以胜任。

namespace Test2
{
    internal static class MyProgram
    {
        [STAThread]
        private static void Main(string[] args)
        {
            List<Plugin> plugins = new List<Plugin>
                                       {
                                           new Plugin(@"c:\temp\file1.txt"),
                                           new Plugin(@"c:\temp\file2.txt"),
                                           new Plugin(@"c:\temp\file3.txt"),
                                       };

            foreach (var plugin in plugins)
            {
                // I need StartWatch to be called only after i got OnChanged() for the previous plugin
                plugin.StartWatch();
                plugin.WaitHandler.WaitOne();
            }
        }
    }


    public class Plugin
    {
        private FileSystemWatcher _watcher;
        private readonly string _file;
        public AutoResetEvent WaitHandler {get;private set;} 

        public Plugin(string file)
        {
            _file = file;
            Console.WriteLine("Creating plugin for file {0}", _file);
            WaitHandler = new AutoResetEvent(false);
        }

        public void StartWatch()
        {
            Console.WriteLine("Starting watching {0}", _file);
            WaitHandler.Reset();
            FileInfo fileInfo = new FileInfo(_file);
            if (fileInfo.Directory != null)
            {
                _watcher = new FileSystemWatcher(fileInfo.Directory.FullName, fileInfo.Name);
                _watcher.NotifyFilter = NotifyFilters.LastWrite;
                _watcher.Changed += OnChanged;
                _watcher.EnableRaisingEvents = true;
            }
            // i want the main thread to be paused untill i get the OnChanged()
        }

        private void OnChanged(object source, FileSystemEventArgs e)
        {
            Console.WriteLine("Finished watching file {0}", _file);
            _watcher.Dispose();

            // once i get this event, i want the main thread to continue and to start watching the same plugin
            WaitHandler.Set();
        }
    }
}