FileSystemWatcher事件多次触发的解决方法
来源:互联网 发布:everying软件搜图片 编辑:程序博客网 时间:2024/06/05 11:44
1、问题描述
程序里需要监视某个目录下的文件变化情况: 一旦目录中出现新文件或者旧的文件被覆盖,程序需要读取文件内容并进行处理。于是使用了下面的代码:
{
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事件被反复触发了好几次。这样可能的结果是造成同一文件的重复处理。 研究了log4net的代码 - XmlConfigurator.cs,然后参照log4net对代码作了如下改动: (2). 初始化FileSystemWatcher和定时器 (3). 文件监视事件触发代码:修改定时器,记录文件名待以后处理 (4). 定时器事件触发代码:进行文件的实际处理 将上面的代码整理一下,封装成一个类,使用上更加便利一些: 在主调程序使用非常简单,只需要如下2步: 其中fsw_Changed是你自己的文件监视事件代码,将它传递给定时器对象的目的是用于定时到时的时候定时器对象可以调用你自己真正用于处理文件的代码。例如: 2、将FileSystemWatcher的Create/Change/Rename/Delete等事件句柄关联到定时器的事件上 这一步的目的是当有任何文件监视事件发生时,都能通知到定时器,定时器可以从最后一次发生的事件开始计时,在该计时未到时之前的任何事件都只会重新使计时器计时,而不会真正触发文件监视事件。
2、解决方案:
在Google上进行一番搜索后,得到了下面的一段信息: <<http://www.cnblogs.com/RicCC/archive/2006/12/16/filesystem-watcher.html>>
"...可以参考log4net的做法。通过一个计时器,在文件事件处理中让计时器延迟一段时间之后,再执行加载新的配置文件操作。这样可以避免对文件做一次操作触发了多个更改事件,而多次加载配置文件。"
基本思想是使用定时器,在事件触发时开始启动定时器,并记下文件名。当定时器到时,才真正对文件进行处理。
(1). 定义变量
System.IO.FileSystemWatcher fsw = new System.IO.FileSystemWatcher();
System.Threading.Timer m_timer = null;
List<String> files = new List<string>(); //记录待处理文件的队列
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);
}
{
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);
}
{
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");
}
}
{
private int TimeoutMillis = 2000;
System.IO.FileSystemWatcher fsw = new System.IO.FileSystemWatcher();
System.Threading.Timer m_timer = null;
List<String> files = new List<string>();
FileSystemEventHandler fswHandler = null;
public WatcherTimer(FileSystemEventHandler watchHandler)
{
m_timer = new System.Threading.Timer(new TimerCallback(OnTimer),
null, Timeout.Infinite, Timeout.Infinite);
fswHandler = watchHandler;
}
public WatcherTimer(FileSystemEventHandler watchHandler, int timerInterval)
{
m_timer = new System.Threading.Timer(new TimerCallback(OnTimer),
null, Timeout.Infinite, Timeout.Infinite);
TimeoutMillis = timerInterval;
fswHandler = watchHandler;
}
public void OnFileChanged(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);
}
private void OnTimer(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)
{
fswHandler(this, new FileSystemEventArgs(
WatcherChangeTypes.Changed, string.Empty, file));
}
}
}
1、生成用于文件监视的定时器对象
{
//Read file.
//Remove file from folder after reading
}
fsw.Changed += new FileSystemEventHandler(watcher.OnFileChanged);
fsw.Renamed += new RenamedEventHandler(watcher.OnFileChanged);
fsw.Deleted += new FileSystemEventHandler(watcher.OnFileChanged);
要注意的是,采用了以上的代码后,你真正用于处理文件监视事件的代码被调用的时候只有其中的e.Name是有值的。考虑到被监视的文件目录应该已经知道了,所以e.FullPath被赋值为string.Empty并不是不能接受的。
- FileSystemWatcher事件多次触发的解决方法
- FileSystemWatcher事件多次触发的解决方法
- FileSystemWatcher事件多次触发的解决方法
- FileSystemWatcher事件多次触发的解决方法
- FileSystemWatcher事件多次触发的解决方法 (C++版)
- 解决FileSystemWatcher事件多次触发的方法
- FileSystemWatcher触发多次Change事件的解决办法
- FileSystemWatcher触发多次Change事件的解决办法
- FileSystemWatcher事件多次触发解决办法
- FileSystemWatcher 解决多次出发OnChanged事件
- window.onresize 多次触发的解决方法
- UIButton事件防止多次触发的写法
- 关于表单提交按钮多次点击多次触发的解决方法
- mouseover多次触发事件
- FileSystemWatcher是软件程序开发常用到的一个监控组件,但是这个控件的Changed 时间方法老是触发2次或者多次,触发多次的情况
- reactiveCocoa rac_signalForControlEvents多次触发解决方法
- click事件多次触发 jquery
- jQuery click事件多次触发
- undefined reference to rpl_malloc
- MFC中CTreeView的使用
- 用SQLDMO在ASP.NET中备份和还原数据库(SQLSERVER2000)
- (原创)技术全面才算牛人,还是术业有专攻
- 强力重置ASP.NET membership加密后的密码!
- FileSystemWatcher事件多次触发的解决方法
- oracle DECODE函数
- 【转载】opencv中的一些宏
- 解读shell之批量添加账户
- [ACE程序员教程笔记]使用ACE_Connector连接服务器
- Apache开源软件目录
- 银行业务调度系统心得
- mysql data too long for column xxx解决方案
- GStreamer: Open Source Multimedia Framework