惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 聂微东
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 三生石上(FineUI控件)
T
Tailwind CSS Blog
Apple Machine Learning Research
Apple Machine Learning Research
Hugging Face - Blog
Hugging Face - Blog
爱范儿
爱范儿
博客园 - 司徒正美
人人都是产品经理
人人都是产品经理
Jina AI
Jina AI
博客园 - 叶小钗
雷峰网
雷峰网
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
WordPress大学
WordPress大学
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
阮一峰的网络日志
阮一峰的网络日志
量子位

博客园 - winkingzhang

Build 2016概览 WinRT开发系列之编程语言:功能和效率 WinRT开发系列之基础概念:WinRT不是…… VS2010 Extension实践(3)——实现自定义配置 [VS2010 Extension]PowerExtension.GoToDefinition VS2010 Extension实践(2) VS2010 Extension实践 如何通过反射调用带有ref或者out的参数的方法[迁移] Win7硬盘安装和移动硬盘访问出错的修复办法[迁移] zt. Windows Mobile开发文章收藏 [WPF]在Style中设置ToolTip的问题分析 [WPF]RadioButton在Group的Header区部分不响应鼠标选择的bug分析 WPF模式思考 (zt) How to Get IIS Web Sites Information Programmatically Visual Studio 调试器 Application Request Routing and the IIS 7.0 Web Management Service Reference Resources for MOSS and WSS ASP.NET Application Life Cycle CAS and Native Code
FileSystemWatcher事件多次触发的解决方法
winkingzhang · 2008-07-04 · via 博客园 - winkingzhang

 转自:http://www.cnblogs.com/dragon/archive/2008/07/04/filesystemwatcher.html
1、问题描述
     
程序里需要监视某个目录下的文件变化情况: 一旦目录中出现新文件或者旧的文件被覆盖,程序需要读取文件内容并进行处理。于是使用了下面的代码:

public void Initial()
{
   System.IO.FileSystemWatcher fsw 
= new System.IO.FileSystemWatcher();            
   fsw.Filter 
= "*.*";
   fsw.NotifyFilter 
= NotifyFilters.FileName  | 
                      NotifyFilters.LastWrite 
| 
                      NotifyFilters.CreationTime;

   
// Add event handlers.
   fsw.Created += new FileSystemEventHandler(fsw_Changed);
   fsw.Changed 
+= new FileSystemEventHandler(fsw_Changed);

   
// Begin watching.
   fsw.EnableRaisingEvents = true;
}

 
void fsw_Changed(object sender, FileSystemEventArgs e)
{
   MessageBox.Show(
"Changed", e.Name);
}

结果发现当一个文件产生变化时,Change事件被反复触发了好几次。这样可能的结果是造成同一文件的重复处理。
2、解决方案:
在Google上进行一番搜索后,得到了下面的一段信息: <<http://www.cnblogs.com/RicCC/archive/2006/12/16/filesystem-watcher.html>>
"...可以参考log4net的做法。通过一个计时器,在文件事件处理中让计时器延迟一段时间之后,再执行加载新的配置文件操作。这样可以避免对文件做一次操作触发了多个更改事件,而多次加载配置文件。"

研究了log4net的代码 - XmlConfigurator.cs,然后参照log4net对代码作了如下改动:
基本思想是使用定时器,在事件触发时开始启动定时器,并记下文件名。当定时器到时,才真正对文件进行处理。
(1). 定义变量

private int TimeoutMillis = 2000//定时器触发间隔
System.IO.FileSystemWatcher fsw = new System.IO.FileSystemWatcher();
System.Threading.Timer m_timer 
= null;
List
<String> files = new List<string>(); //记录待处理文件的队列

(2). 初始化FileSystemWatcher和定时器

fsw.Filter = "*.*";
fsw.NotifyFilter 
= NotifyFilters.FileName  | 
                     NotifyFilters.LastWrite 
| 
                     NotifyFilters.CreationTime;

// Add event handlers.
fsw.Created += new FileSystemEventHandler(fsw_Changed);
fsw.Changed 
+= new FileSystemEventHandler(fsw_Changed);

// Begin watching.
fsw.EnableRaisingEvents = true;

// Create the timer that will be used to deliver events. Set as disabled
if (m_timer == null)
{
      
//设置定时器的回调函数。此时定时器未启动
      m_timer = new System.Threading.Timer(new TimerCallback(OnWatchedFileChange),  null, Timeout.Infinite, Timeout.Infinite);
}

(3). 文件监视事件触发代码:修改定时器,记录文件名待以后处理

void fsw_Changed(object sender, FileSystemEventArgs e)
{
    Mutex mutex 
= new Mutex(false"FSW");
    mutex.WaitOne();
    
if (!files.Contains(e.Name))
      
{
        files.Add(e.Name);
    }

    mutex.ReleaseMutex();

    
//重新设置定时器的触发间隔,并且仅仅触发一次
    m_timer.Change(TimeoutMillis, Timeout.Infinite);
}

(4). 定时器事件触发代码:进行文件的实际处理

private void OnWatchedFileChange(object state)
{
    List
<String> backup = new List<string>();

    Mutex mutex 
= new Mutex(false"FSW");
    mutex.WaitOne();
    backup.AddRange(files);
    files.Clear();
    mutex.ReleaseMutex();
    
    
foreach (string file in backup)
      
{
        MessageBox.Show(
"File Change", file + " changed");
    }

}

完整的代码请下载示例程序