解决FileSystemWatcher事件多次触发的方法

解决FileSystemWatcher事件多次触发的方法

作者: 江大鱼 发表于 2008-07-23 21:55 原文链接 阅读: 968 评论: 2

 

博客园已有几位同学发表了关于FileSystemWatcher事件多次触发的解决方法的文章,很好地解决了事件多次激发的问题。

主要方法有:

1.延迟激发法。

http://www.cnblogs.com/dragon/archive/2008/07/04/filesystemwatcher.html

原理是延迟调用事件的代理,将多次事件合并为一次,从而很好的解决了此问题,唯一的缺憾是时间激发不及时,不适用于实时性较高的系统。

2.临时禁用法。

 

 1: void watcher_Changed(object sender, FileSystemEventArgs e)
 2: {
     
 3: if (watcher != null)
 4: {
     
 5: //解决执行两次的问题 
 6: watcher.EnableRaisingEvents = false;
 7: Thread th = new Thread(new ThreadStart(
 8: delegate()
 9: {
     
 10: Thread.Sleep(1000);
 11: watcher.EnableRaisingEvents = true;
 12: }
 13: ));
 14: th.Start();
 15: }
 16: }

这种方法是监视单个文件的情况下的最简单解决办法。但是很明显,在监视多个文件的情况下就有很大的问题,文件的事件很可能丢失,在高并发的情况下很容易出问题。

 

我这里要提出的新的方法叫“检查最后更新时间法”,原理是在FileSystemWatcher事件激发时先检查更新的文件的最后更新时间是否已经被记录, 如果未被记录则激发event,否则不激发。

具体代码如下

 1: using System;
 2: using System.Collections.Generic;
 3: using System.Linq;
 4: using System.Text;
 5: using System.IO;
 6: 
 7: namespace GiantSoft.Common
 8: {
     
 9: public class GiantFileSystemWatcher : IDisposable
 10: {
     
 11: private FileSystemWatcher m_Watcher;
 12: 
 13: private Dictionary<string, DateTime> m_DictUpdateTime = new Dictionary<string, DateTime>();
 14: 
 15: public GiantFileSystemWatcher(string path, string filter)
 16: {
     
 17: m_Watcher = new FileSystemWatcher(path, filter);
 18: m_Watcher.Error += new ErrorEventHandler(m_Watcher_Error);
 19: m_Watcher.EnableRaisingEvents = false;
 20: m_Watcher.IncludeSubdirectories = true;
 21: }
 22: 
 23: void m_Watcher_Error(object sender, ErrorEventArgs e)
 24: {
     
 25: LogUtil.LogError(e.GetException());
 26: }
 27: 
 28: public bool Start()
 29: {
     
 30: if (m_FileChangeHandler != null)
 31: {
     
 32: m_Watcher.Changed += new FileSystemEventHandler(m_Watcher_Changed);
 33: m_Watcher.Created += new FileSystemEventHandler(m_Watcher_Changed);
 34: m_Watcher.Renamed += new RenamedEventHandler(m_Watcher_Changed);
 35: m_Watcher.EnableRaisingEvents = true;
 36: return true;
 37: }
 38: else
 39: {
     
 40: return false;
 41: }
 42: }
 43: 
 44: void m_Watcher_Changed(object sender, FileSystemEventArgs e)
 45: {
     
 46: try
 47: {
     
 48: DateTime lastModifyTime = File.GetLastWriteTime(e.FullPath);
 49: DateTime prevModifyTime = DateTime.MinValue;
 50: 
 51: if (m_DictUpdateTime.TryGetValue(e.FullPath.ToLower(), out prevModifyTime))
 52: {
     
 53: if (lastModifyTime <= prevModifyTime)
 54: {
     
 55: return;
 56: }
 57: else
 58: {
     
 59: m_DictUpdateTime[e.FullPath.ToLower()] = lastModifyTime;
 60: }
 61: }
 62: else
 63: {
     
 64: m_DictUpdateTime[e.FullPath.ToLower()] = lastModifyTime;
 65: }
 66: 
 67: if (m_FileChangeHandler != null)
 68: {
     
 69: m_FileChangeHandler.Invoke(this, e);
 70: }
 71: }
 72: catch (Exception exc)
 73: {
     
 74: LogUtil.LogError(exc);
 75: }
 76: }
 77: 
 78: private FileSystemEventHandler m_FileChangeHandler;
 79: 
 80: public event FileSystemEventHandler FileChangeHandler
 81: {
     
 82: add { m_FileChangeHandler += value; }
 83: remove { m_FileChangeHandler -= value; }
 84: }
 85: 
 86: #region IDisposable Members
 87: 
 88: public void Dispose()
 89: {
     
 90: m_DictUpdateTime.Clear();
 91: m_DictUpdateTime = null;
 92: m_Watcher.EnableRaisingEvents = false;
 93: if (m_FileChangeHandler != null)
 94: {
     
 95: m_Watcher.Changed -= new FileSystemEventHandler(m_Watcher_Changed);
 96: m_Watcher.Created -= new FileSystemEventHandler(m_Watcher_Changed);
 97: m_Watcher.Renamed -= new RenamedEventHandler(m_Watcher_Changed);
 98: }
 99: m_Watcher.Dispose();
 100: }
 101: 
 102: #endregion
 103: }
 104: }

 

 

 

这种解决方法能够满足绝大部分的需求,但是对于监视数量巨大的文件会有性能问题,Dictionary的性能会随着文件数量的增加而降低。

作者:
江大鱼

出处:
http://jzywh.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

解决FileSystemWatcher事件多次触发的方法

评论: 2 查看评论 发表评论

软件研发团队管理年会(上海,7.10-7.11)


最新新闻:
· 6个强大的社会化网络搜索引擎(2010-06-12 08:58)
· 马雪征:把联想的经验带入TPG(2010-06-12 08:54)
· 苹果如何基业长青(2010-06-12 08:52)
· 腾讯:平台优势催动“利润发生器”(2010-06-12 08:52)
· Google News测试新版页面(2010-06-12 08:50)

编辑推荐:谈谈IT软件开发工程师的基本功

网站导航:博客园首页  个人主页  新闻  闪存  小组  博问  社区  知识库

转载于:https://my.oschina.net/kjiang/blog/5515

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110764.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 激活码2089(已测有效)

    激活码2089(已测有效),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月14日
    100
  • 微信小程序实现上传图片功能[通俗易懂]

    微信小程序实现上传图片功能[通俗易懂]效果图WXML<viewclass=”img-wrap”><viewclass=”txt”>上传截图</view><viewclass=”imglist”><viewclass=”item”wx:for=”{{imgs}}”wx:key=”item”><imagesrc=”{{item}}”alt=””></image><viewclass=’d

    2022年6月22日
    166
  • 冯诺依曼计算机特点核心(冯诺依曼计算机体系结构特点)

    冯·诺依曼计算机的特点1.计算机由运算器、存储器、控制器、输入输出设备5大部件组成2.指令和数据以同等地位存储于储存器内,并可按照地址寻访3.指令和数据均用二进制码表示4.指令由操作码和地址码组成5.指令在存储器之中按照顺序存放。通常,指令是顺序执行的,在特定条件下,可以根据运算结果或根据设定的条件改变执行顺序6.机器以运算器为中心,输入输出设备与存储器之间的数据存储必须通过运算器完成。…

    2022年4月18日
    102
  • linux卸载JDK

    linux卸载JDK[root@teajava]#rpm-qa|grepjdk[root@teajava]#rpm-ejdk-1.7.0_79-fcs.x86_64

    2022年10月1日
    1
  • SystemVerilog for循环中的fork join_none「建议收藏」

    SystemVerilog for循环中的fork join_none「建议收藏」moduletest;initialbeginmain();endtaskmain();//forkjoin_anyblock1fork#5$display(“THREAD1%0t”,$time);#25$display(“THREAD2%0t”,$ti…

    2022年9月16日
    2
  • Boost Lockfree「建议收藏」

    Boost Lockfree「建议收藏」BoostLockfreeflyfish2014-9-30为了最大限度的挖掘并行编程的性能考虑使用与锁无关的数据结构来编程与锁无关的数据结构不是依赖于锁和互斥来确保线程安全。Lockfree的重要操作就是CAS(CompareAndSet)原子操作原子操作就是多个线程访问同一个资源时,有且仅有唯一一个线程对该资源进行操作BOOST中的宏定义BOOST_

    2022年7月19日
    24

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号