您的位置:首页 > 其它

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

2008-07-23 21:55 645 查看
博客园已有几位同学发表了关于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

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: