【www.gdgbn.com--php安全】

c# filesystemwatcher 文件监控对象使用

用了线程安全的hashtable来处理一次改变触发两次事件的问题,要注意的是在实际项目使用中,在通过监控文件事情触发时开一个线程watcherprocess去处理自己业务逻辑的时候,不管业务逻辑成功或者失败(例如有异常抛出一定要try一下)一定要让watcherprocess的 completed也就是myfilesystemwather的watcherprocess_oncompleted执行去移除对应变化文件的hashtable的key,不然下次此文件改变时是无法触发你的业务逻辑的。

   

     还有就是在进行文件监控的时候, 被监控文件在写入的时候,是会有i/o冲突的,即使写入文件是fileshare.read的也会出现,要真正解决貌似只有filemaping方法,但是我的项目中文本的写入软件不是我们能控制的,所以只有用处理异常的方法来解决。

 

using system;
using system.io;

namespace test
{
    class program
    {
        static void main(string[] args)
        {


            watcherstrat(@"c:test", "*.txt");
            //由于是控制台程序,加个输入避免主线程执行完毕,看不到监控效果
            console.readkey();

        }

     

        private static void watcherstrat(string path, string filter)
        {
            filesystemwatcher watcher = new filesystemwatcher();
            watcher.path = path;

            watcher.filter = filter;

            watcher.changed += new filesystemeventhandler(onprocess);
            watcher.created += new filesystemeventhandler(onprocess);
            watcher.deleted += new filesystemeventhandler(onprocess);
            watcher.renamed += new renamedeventhandler(onrenamed);

            watcher.enableraisingevents = true;
        }

 


        private static void onprocess(object source, filesystemeventargs e)
        {
            if (e.changetype == watcherchangetypes.created)
            {
                oncreated(source, e);

            }
            else if (e.changetype == watcherchangetypes.changed)
            {
                onchanged(source, e);

            }
            else if (e.changetype == watcherchangetypes.deleted)
            {
                ondeleted(source, e);

            }
        }

        private static void oncreated(object source, filesystemeventargs e)
        {

            console.writeline("文件新建事件处理逻辑");
           
        }

        private static void onchanged(object source, filesystemeventargs e)
        {

            console.writeline("文件改变事件处理逻辑");
        }

        private static void ondeleted(object source, filesystemeventargs e)
        {

            console.writeline("文件删除事件处理逻辑");
        }

        private static void onrenamed(object source, renamedeventargs e)
        {

            console.writeline("文件重命名事件处理逻辑");
        }

    }
}

myfilesystemwather类:

using system;
using system.collections;
using system.io;
using system.threading;

namespace test
{

    public delegate void completed(string key);

    public class myfilesystemwather
    {
        private filesystemwatcher fswather;

        private hashtable hstbwather;

        public event renamedeventhandler onrenamed;
        public event filesystemeventhandler onchanged;
        public event filesystemeventhandler oncreated;
        public event filesystemeventhandler ondeleted;

        ///


        /// 构造函数
        ///

        /// 要监控的路径
        public myfilesystemwather(string path, string filter)
        {
            if (!directory.exists(path))
            {
                throw new exception("找不到路径:" + path);
            }

            hstbwather = new hashtable();

            fswather = new filesystemwatcher(path);
            // 是否监控子目录
            fswather.includesubdirectories = false;
            fswather.filter = filter;
            fswather.renamed += new renamedeventhandler(fswather_renamed);
            fswather.changed += new filesystemeventhandler(fswather_changed);
            fswather.created += new filesystemeventhandler(fswather_created);
            fswather.deleted += new filesystemeventhandler(fswather_deleted);
        }

        ///


        /// 开始监控
        ///

        public void start()
        {
            fswather.enableraisingevents = true;
        }

        ///


        /// 停止监控
        ///

        public void stop()
        {
            fswather.enableraisingevents = false;
        }

        ///


        /// filesystemwatcher 本身的事件通知处理过程
        ///

        ///
        ///
        private void fswather_renamed(object sender, renamedeventargs e)
        {
            lock (hstbwather)
            {
                hstbwather.add(e.fullpath, e);
            }

            watcherprocess watcherprocess = new watcherprocess(sender, e);
            watcherprocess.oncompleted += new completed(watcherprocess_oncompleted);
            watcherprocess.onrenamed += new renamedeventhandler(watcherprocess_onrenamed);
            thread thread = new thread(watcherprocess.process);
            thread.start();
        }

        private void watcherprocess_onrenamed(object sender, renamedeventargs e)
        {
            onrenamed(sender, e);
        }

        private void fswather_created(object sender, filesystemeventargs e)
        {
            lock (hstbwather)
            {
                hstbwather.add(e.fullpath, e);
            }
            watcherprocess watcherprocess = new watcherprocess(sender, e);
            watcherprocess.oncompleted += new completed(watcherprocess_oncompleted);
            watcherprocess.oncreated += new filesystemeventhandler(watcherprocess_oncreated);
            thread threaddeal = new thread(watcherprocess.process);
            threaddeal.start();
        }

        private void watcherprocess_oncreated(object sender, filesystemeventargs e)
        {
            oncreated(sender, e);
        }

        private void fswather_deleted(object sender, filesystemeventargs e)
        {
            lock (hstbwather)
            {
                hstbwather.add(e.fullpath, e);
            }
            watcherprocess watcherprocess = new watcherprocess(sender, e);
            watcherprocess.oncompleted += new completed(watcherprocess_oncompleted);
            watcherprocess.ondeleted += new filesystemeventhandler(watcherprocess_ondeleted);
            thread tddeal = new thread(watcherprocess.process);
            tddeal.start();
        }

        private void watcherprocess_ondeleted(object sender, filesystemeventargs e)
        {
            ondeleted(sender, e);
        }

        private void fswather_changed(object sender, filesystemeventargs e)
        {
            if (e.changetype == watcherchangetypes.changed)
            {
                if (hstbwather.containskey(e.fullpath))
                {
                    watcherchangetypes oldtype = ((filesystemeventargs)hstbwather[e.fullpath]).changetype;
                    if (oldtype == watcherchangetypes.created || oldtype == watcherchangetypes.changed)
                    {
                        return;
                    }
                }
            }

            lock (hstbwather)
            {
                hstbwather.add(e.fullpath, e);
            }
            watcherprocess watcherprocess = new watcherprocess(sender, e);
            watcherprocess.oncompleted += new completed(watcherprocess_oncompleted);
            watcherprocess.onchanged += new filesystemeventhandler(watcherprocess_onchanged);
            thread thread = new thread(watcherprocess.process);
            thread.start();
        }

        private void watcherprocess_onchanged(object sender, filesystemeventargs e)
        {
            onchanged(sender, e);
        }

        public void watcherprocess_oncompleted(string key)
        {
            lock (hstbwather)
            {
                hstbwather.remove(key);
            }
        }
    }
}

分析

filesystemwatcher基础

属性:

    path——这个属性告诉filesystemwatcher它需要监控哪条路径。例如,如果我们将这个属性设为“c:test”,对象就监控test目录下所有文件发生的所有改变(包括删除,修改,创建,重命名)。

    includesubdirectories——这个属性说明filesystemwatcher对象是否应该监控子目录中(所有文件)发生的改变。

    filter——这个属性允许你过滤掉某些类型的文件发生的变化。例如,如果我们只希望在txt文件被修改/新建/删除时提交通知,可以将这个属性设为“*txt”。在处理高流量或大型目录时,使用这个属性非常方便。

notifyfilter——获取或设置要监视的更改类型。可以进一步的过滤要监控的更改类型,如watcher.notifyfilter = notifyfilters.lastaccess | notifyfilters.lastwrite

           | notifyfilters.filename | notifyfilters.directoryname;

事件:

    changed——当被监控的目录中有一个文件被修改时,就提交这个事件。值得注意的是,这个事件可能会被提交多次,即使文件的内容仅仅发生一项改变。这是由于在保存文件时,文件的其它属性也发生了改变。

    created——当被监控的目录新建一个文件时,就提交这个事件。如果你计划用这个事件移动新建的事件,你必须在事件处理器中写入一些错误处理代码,它能处理当前文件被其它进程使用的情况。之所以要这样做,是因为created事件可能在建立文件的进程释放文件之前就被提交。如果你没有准备正确处理这种情况的代码,就可能出现异常。

    deleted——当被监控的目录中有一个文件被删除,就提交这个事件。

    renamed——当被监控的目录中有一个文件被重命名,就提交这个事件。 

 

注:如果你没有将enableraisingevents设为真,系统不会提交任何一个事件。如果有时filesystemwatcher对象似乎无法工作,请首先检查enableraisingevents,确保它被设为真。

 

事件处理

 

当filesystemwatcher调用一个事件处理器时,它包含两个自变量——一个叫做“sender”的对象和一个叫做“e”的 filesystemeventargs对象。我们感兴趣的自变量为filesystemeventargs自变量。这个对象中包含有提交事件的原因。以下是filesystemeventargs对象的一些属性:

 

属性:

 

  name——这个属性中使事件被提交的文件的名称。其中并不包含文件的路径——只包含使用事件被提交的文件或目录名称。

  changetype——这是一个watcherchangetypes,它指出要提交哪个类型的事件。其有效值包括:

  changed

  created

  deleted

  renamed

  fullpath——这个属性中包含使事件被提交的文件的完整路径,包括文件名和目录名。

 

注意:filesystemeventargs对象是监控文件夹下有文件创建、删除、修改时的自变量,如果是重命名的话为renamedeventargs对象此时除了filesystemeventargs对象的属性值,多了一个oldfullpath,为重命名之前的文件名。

 

以上为filesystemeventargs的基本知识,大部分是从网上搜找的然后自己稍微整理了一下。

本文来源:http://www.gdgbn.com/jiaocheng/28902/