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

推荐订阅源

Google Online Security Blog
Google Online Security Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
C
CERT Recently Published Vulnerability Notes
C
Cybersecurity and Infrastructure Security Agency CISA
Cisco Talos Blog
Cisco Talos Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Scott Helme
Scott Helme
Project Zero
Project Zero
E
Exploit-DB.com RSS Feed
S
Secure Thoughts
K
Kaspersky official blog
L
Lohrmann on Cybersecurity
NISL@THU
NISL@THU
WordPress大学
WordPress大学
N
News and Events Feed by Topic
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LINUX DO - 热门话题
小众软件
小众软件
P
Privacy & Cybersecurity Law Blog
博客园 - 聂微东
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
A
About on SuperTechFans
Hacker News: Ask HN
Hacker News: Ask HN
AWS News Blog
AWS News Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Hacker News: Front Page
F
Full Disclosure
Latest news
Latest news
Schneier on Security
Schneier on Security
The Hacker News
The Hacker News
T
Troy Hunt's Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Jina AI
Jina AI
Martin Fowler
Martin Fowler
P
Proofpoint News Feed
TaoSecurity Blog
TaoSecurity Blog
G
GRAHAM CLULEY
Forbes - Security
Forbes - Security
V
V2EX - 技术
酷 壳 – CoolShell
酷 壳 – CoolShell
V
Vulnerabilities – Threatpost
C
Cyber Attacks, Cyber Crime and Cyber Security
MongoDB | Blog
MongoDB | Blog
博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog
P
Privacy International News Feed
C
Check Point Blog
N
News and Events Feed by Topic

博客园 - 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");
    }

}

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