C# FileSystemWatcher 内建类 监控文件的变化

[转Technical Tips]

概述:

今天给大家简单介绍一下C#的内部类FileSystemWatcher

要是你的日常工作中需要做有关文件或者目录监控的功能,别忘了用这个.Net内建类。用它可以很容易地做出类似日志分析监控、文件自动化处理等等工具。

 

一个简单的例子如下:

    FileSystemWatcher fw=newFileSystemWatcher(path, filter);

    fw.InternalBufferSize=65536; //64k                   

    fw.Created+=fw_Created; //当有文件被创建的时候,fw_Created事件处理方法就会被调用;

    fw.Changed+=fw_Changed; //文件被修改时

    fw.Deleted+=fw_Deleted; //文件被删除时

    fw.Renamed+=fw_Renamed; //文件被改名时

    fw.Error+=fw_Error; //当FileSystemWatcher申请的用来监控文件变化的内存区域有溢出错误时

    fw.EnableRaisingEvents=true; //打开关闭文件监控

 

这样,一个非常简单的文件监控功能,就做好了,在具体处理文件变化的事件中,再加上你自己对文件处理的逻辑,就没问题了。

 

但是要说明的是,在文件新建、变化、改名、删除的事件处理方法里,最好是新开一个线程来对具体文件进行操作。尤其,当这些操作需要同步、串行处理的话,那么最好还要使用一个队列来作为待处理文件的缓存池。

这样做是必须的,因为FileSystemWatcher的原理是在内存中使用一小块会被Windows优先响应的内存区域。这些资源很宝贵,所以FileSystemWatcher最多只能设置64K的大小,默认的话,它是用8K。如果你在事件响应方法里做太多事情,浪费太多时间,那么当你监控的目录下同时有很多很多文件事件发生时,就会发生“溢出”,简单来说,就是这个文件监控功能,有些文件的变化,没有抓到。所以,另外开线程处理文件是明智之举,让事件处理方法只作为一个“收发室”。

 

另外一个要说明的是,文件新建的事件会在文件一创建的时候就会发生,这个时候如果你想处理文件,可能会有问题,因为这个文件可能还没有被准备好(比如copy一个1G的电影,是要花一些时间的,但是在copy刚开始的时候,文件在硬盘上被创建,那么“新建”这个事件就发生了)。所以这个时候,就需要通过“轮询”的方法等待文件准备完成。没什么好方法,上StackOverflow查了,全世界的程序猿都纠结这个问题,但是最后都选择了用“轮询、独占方式打开”的方法来验证文件是不是准备好了。具体代码如下:

privatestaticboolIsFileReady(stringfullPath)

{

    intwaitTime=0;

    inttimeout=60 *1000; // 等待超时时间,1分钟

    intcheckTime=100; // 轮询等待时间,0.1秒

    do

    {

        if (waitTime>timeout)

        {

            returnfalse; // 等待超时

        }

 

        try

        {

            using (FileStreamfs=File.Open(fullPath, FileMode.Open, FileAccess.Read, FileShare.None))

            { }

            returntrue; // 文件准备就绪

        }

        catch

        {

            Thread.Sleep(checkTime); // 等待0.1秒

            waitTime+=checkTime;

        }

    } while (true);

}

 

最后要说明的是,“文件变化”事件的产生比较有趣,当一个文件被保存的时候,会产生好几次“文件变化”事件。这是因为在Windows写文件的时候,会“改变内容”,“改变的大小属性”,“改变文件的最后修改时间属性”等等,每一次对文件的改动,都会触发“文件变化”事件。所以,想监控文件的变化,需要小心一点。

posted @ 2014-12-11 14:46  Blackeye  阅读(1173)  评论(1编辑  收藏  举报