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

评论: 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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值