System.IO.FileSystemWatcher

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了System.IO.FileSystemWatcher相关的知识,希望对你有一定的参考价值。

这个类功能很强。可以实时监测文件系统的变化。

https://msdn.microsoft.com/zh-cn/library/system.io.filesystemwatcher.aspx

事件

技术分享

使用不如预期。重复发送消息、结束时并不会发送消息。

例如,拷贝一个文件,在文件拷贝完成后进行操作,但我们无法知道什么时候拷贝操作完成。

拷贝文件时,响应的事件:Created、Changed、Changed(...)

其实,知道这些就已经可以了。

新增文件时,首先收到Created消息。下面我们需要做一些额外的工作来监视文件是否写入完毕。

这里使用了独占方式读取文件,发生异常,表示写入未完成。 

using (FileStream fs = new System.IO.FileStream(item.FullPath, FileMode.Open, FileAccess.Read, FileShare.None))
{
     fs.Close();
}

当收到Created消息后,在while中独占读取文件。

创建监听对象,扩展了多类型监听。

FileWatcher.Start(FullPath, "*.txt|*.dwg");

public class FileWatcher
    {
        string _folder;
        string _filter;
        System.IO.FileSystemWatcher _watcher;
        private FileWatcher(string folder):this(folder,string.Empty)
        {
        }
        private FileWatcher(string folder,string filter) {
            if (string.IsNullOrEmpty(folder))
                throw new ArgumentNullException("folder");
            this._folder = folder;
            this._filter = filter;

            _watcher = new System.IO.FileSystemWatcher(this._folder);
            _watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite |NotifyFilters.FileName;
            _watcher.IncludeSubdirectories = true;
            if (!string.IsNullOrEmpty(this._filter))
                _watcher.Filter = this._filter;

            _watcher.Changed += new FileSystemEventHandler(OnChanged);
            _watcher.Created += new FileSystemEventHandler(OnChanged);
            _watcher.Deleted += new FileSystemEventHandler(OnChanged);
            // _watcher.Renamed += new RenamedEventHandler(OnRenamed);

            _watcher.EnableRaisingEvents = true;

        }
        public static void Start(string folder, string filter)
        {
            foreach (var arg in filter.Split(|))
                new FileWatcher(folder, arg);
        }
        private void OnChanged(object source, FileSystemEventArgs e)
        {
            WatcherList.GetInstance().Add(new WatcherInfo() { FullPath = e.FullPath, ChangeType = e.ChangeType });
        }
        private void OnRenamed(object source, RenamedEventArgs e)
        {
        }
    }

 监听对象实体

internal class WatcherInfo
    {
        /// <summary>
        /// 文件全路径
        /// </summary>
        public string FullPath { get; set; }
        /// <summary>
        /// 事件发生事件
        /// </summary>
        internal DateTime EventTime { get; set; }
        /// <summary>
        /// 类型.1,Created.2,Deleted。3.Changed
        /// </summary>
        public WatcherChangeTypes ChangeType { get; set; }
        /// <summary>
        /// 0:正常
        /// </summary>
        internal int Status { get; set; }
    }
/// <summary>
    /// 假设同名的文件只进行一次操作
    /// </summary>
    internal class WatcherList
    {
        private static readonly object syncObject = new object();
        private static WatcherList singleton;
        private Queue<WatcherInfo> All = new Queue<WatcherInfo>();
        ManualResetEvent allDone = new ManualResetEvent(false);

        private WatcherList()
        {
            System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(this.Work));
        }
        public static WatcherList GetInstance()
        {
            if (singleton == null)
            {
                lock (syncObject)
                {
                    if(singleton==null)
                        singleton = new WatcherList();
                }
            }
            return singleton;
        }
        public void Add(WatcherInfo i)
        {
            if (i == null|| string.IsNullOrEmpty(i.FullPath)) return;
            if (i.ChangeType == WatcherChangeTypes.Created)
                Enqueue(i);
            else if (i.ChangeType == WatcherChangeTypes.Deleted)
                Dequeue(i);
        }
        private void Enqueue(WatcherInfo i)
        {
            if (i.ChangeType != WatcherChangeTypes.Created)
                return;
            bool isadd = false;
            lock (syncObject)
            {
                foreach (var item in All)
                {
                    if (i.FullPath == item.FullPath &&
                        i.ChangeType == WatcherChangeTypes.Created)
                    {
                        isadd = true;
                        break;
                    }
                }
                if (!isadd)
                {
                    i.Status = 0;
                    i.EventTime = DateTime.Now;
                    All.Enqueue(i);
                    allDone.Set();
                }
            }
        }
        private void Dequeue(WatcherInfo i)
        {
            if (i.ChangeType != WatcherChangeTypes.Deleted)
                return;
            lock (syncObject)
            {
                foreach (var item in All)
                {
                    if (i.FullPath == item.FullPath)
                        item.Status = 1;
                }
            }
        }
        private void Work(Object o)
        {
            while (true)
            {
                if (All.Count == 0)
                    allDone.WaitOne();
                if (All.Count == 0)/*必要*/
                    continue;
                var item = All.Peek();
                if (item.Status == 1)
                    All.Dequeue();
                else
                {
                    if (!System.IO.File.Exists(item.FullPath))
                    {
                        {
                            All.Dequeue(); 
                            continue;
                        }
                    }
                    try
                    {
                        using (FileStream fs = new System.IO.FileStream(item.FullPath, FileMode.Open, FileAccess.Read, FileShare.None))
                        {
                            fs.Close();
                        }
                       /*
              System.IO.File.Copy
              */
All.Dequeue(); } catch (Exception e) { System.Threading.Thread.Sleep(1000); } } } } }

 

以上是关于System.IO.FileSystemWatcher的主要内容,如果未能解决你的问题,请参考以下文章