解决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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • turtle递归作图绘制谢尔宾斯基地毯【详解】

    turtle递归作图绘制谢尔宾斯基地毯【详解】python数据结构与算法turtle递归作图绘制谢尔宾斯基地毯

    2022年7月13日
    12
  • platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备

    platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备kernel_init中do_basic_setup()-&gt;driver_init()-&gt;platform_bus_init()-&gt;…初始化platformbus(虚拟总线)设备向内核注册的时候platform_device_register()-&gt;platform_device_add()-&gt;…内核把设备挂在虚拟的platformbus下驱动注册…

    2022年7月26日
    1
  • sin的傅里叶变换公式_傅里叶变换的由来及复数下的傅里叶变换公式证明

    sin的傅里叶变换公式_傅里叶变换的由来及复数下的傅里叶变换公式证明1、考虑到一个函数可以展开成一个多项式的和,可惜多项式并不能直观的表示周期函数,由于正余弦函数是周期函数,可以考虑任意一个周期函数能否表示成为一系列正余弦函数的和。假设可以,不失一般性,于是得到:f(t)=A0+∑(n=1,∞)Ansin(nωt+Φn)2、将后面的正弦函数展开:Ansin(nωt+Φn)=AnsinΦncosnωt+AncosΦnsinnωt令a0/2=A0,an…

    2022年7月17日
    14
  • Python语言程序设计基础(1)—— 程序设计基本方法

    Python语言程序设计基础(1)—— 程序设计基本方法Everybodyinthiscountryshouldlearnhowtoprogramacomputer,becauseitteachesyouhowtothink

    2022年7月5日
    15
  • matlab插值函数的作用,matlab 插值函数[通俗易懂]

    matlab插值函数的作用,matlab 插值函数[通俗易懂]MATLAB中的插值函数为interp1,其调用格式为:yi=interp1(x,y,xi,’method’)其中x,y为插值点,yi为在被插值点xi处的插值结果;x,y为向量,’method’表示采用的插值方法,MATLAB提供的插值方法有几种:’method’是最邻近插值,’linear’线性插值;’spline’三次样条插值;’cubic’立方插值.缺省时表示线性插值注意:所…

    2022年6月3日
    66
  • Python之文件操作大全

    Python之文件操作大全在日常工作或生活中,总避免不了需要操作文件或文件夹,比如希望找出电脑中所有临时文件并清除,或者找到指定文件夹内所有图片文件并进行重新命名等等,如果能通过Python脚本的方式解决,会大大提升相关操作效率,本文即总结使用Python进行常见操作相关知识点,方便用到的人随时查阅,不用再每次使用都要花费时间检索或查阅文档。本文主要使用os、shutil、pathlib三个包。一、文件操作1.1文件常规操作操作 代码 说明/示例 新建文件 os.mknod(dir…

    2022年5月7日
    43

发表回复

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

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