code_junkie

VB.NET FileSystemWatcher Multiple Change Events

Nov 13th, 2011
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.37 KB | None | 0 0
  1. Imports System.IO
  2.  
  3. Public Class Blah
  4. Public Sub New()
  5. InitializeComponent()
  6.  
  7. Dim watcher As New FileSystemWatcher("C:")
  8. watcher.EnableRaisingEvents = True
  9.  
  10. AddHandler watcher.Changed, AddressOf watcher_Changed
  11. End Sub
  12.  
  13. Private Sub watcher_Changed(ByVal sender As Object, ByVal e As FileSystemEventArgs)
  14. MsgBox(e.FullPath)
  15. End Sub
  16. End Class
  17.  
  18. if( e.ChangeType == WatcherChangeTypes.Changed )
  19. {
  20.  
  21. // There is a nasty bug in the FileSystemWatch which causes the
  22. // events of the FileSystemWatcher to be called twice.
  23. // There are a lot of resources about this to be found on the Internet,
  24. // but there are no real solutions.
  25. // Therefore, this workaround is necessary:
  26. // If the last time that the event has been raised is only a few msec away,
  27. // we ignore it.
  28. if( DateTime.Now.Subtract (_lastTimeFileWatcherEventRaised).TotalMilliseconds < 500 )
  29. {
  30. return;
  31. }
  32.  
  33.  
  34. _lastTimeFileWatcherEventRaised = DateTime.Now;
  35.  
  36.  
  37. .. handle event
  38.  
  39. private Dictionary<String, FileSystemEventArgs> xmlFileChangedEvents = new Dictionary<string, FileSystemEventArgs>();
  40. private void debugXmlWatcher_Changed(object sender, FileSystemEventArgs e)
  41. {
  42. if (!xmlFileChangedEvents.ContainsKey(e.Name))
  43. xmlFileChangedEvents.Add(e.Name, e);
  44. xmlChangeTimer.Stop();//Reset the Forms.Timer so that it times out in 100 ms
  45. xmlChangeTimer.Start();
  46. }
  47.  
  48. private void xmlChangeTimer_Tick(object sender, EventArgs e)
  49. {
  50. foreach (FileSystemEventArgs eventArg in xmlFileChangedEvents.Values)
  51. {
  52. //
  53. //Handle the file changed event here
  54. //
  55. }
  56. xmlFileChangedEvents.Clear();
  57. }
  58.  
  59. using System;
  60. using System.IO;
  61. using System.Timers;
  62.  
  63. namespace Demo
  64. {
  65. class FileWatcher
  66. {
  67. private FileSystemWatcher watcher = new FileSystemWatcher();
  68. private Timer t = new Timer();
  69.  
  70. public event EventHandler FileChanged;
  71.  
  72. public FileWatcher()
  73. {
  74. t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
  75. t.Interval = 1000;
  76. }
  77.  
  78. public void Start(String path)
  79. {
  80. watcher.Path = Path.GetDirectoryName(path);
  81. watcher.Filter = Path.GetFileName(path);
  82. watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime;
  83. watcher.EnableRaisingEvents = true;
  84. watcher.Changed += new FileSystemEventHandler(watcher_Changed);
  85. }
  86.  
  87. void watcher_Changed(object sender, FileSystemEventArgs e)
  88. {
  89. if (!t.Enabled)
  90. t.Start();
  91. }
  92.  
  93. void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  94. {
  95. t.Stop();
  96. if (FileChanged != null)
  97. FileChanged(this, null);
  98. }
  99. }
  100. }
  101.  
  102. FileWatcher FileWatcher1 = new FileWatcher();
  103. FileWatcher1.FileChanged += new EventHandler(FileWatcher1_FileChanged);
  104. FileWatcher1.Start("c:test.txt");
  105.  
  106. Imports System.IO
  107. Imports System.Threading
  108. Public Class Form1
  109. Private Const MILLISECONDS_TO_WAIT As Integer = 1000
  110. Private fw As FileSystemWatcher
  111. Private Shared AccessEntries As List(Of String)
  112. Private Delegate Sub UpdateBoxDelegate(ByVal msg As String)
  113. Private Sub UpdateBox(ByVal msg As String)
  114. If tbMonitor.InvokeRequired Then
  115. Invoke(New UpdateBoxDelegate(AddressOf UpdateBox), New Object() {msg})
  116. Else
  117. tbMonitor.AppendText(msg + vbCrLf)
  118. End If
  119. End Sub
  120.  
  121. Private Sub AccessEntryRemovalTimer(ByVal RawFileName As Object)
  122. UpdateBox("Sleeping to watch for " + RawFileName.ToString + " on thread ID " + Thread.CurrentThread.ManagedThreadId.ToString)
  123. Thread.Sleep(MILLISECONDS_TO_WAIT)
  124. AccessEntries.Remove(RawFileName.ToString)
  125. UpdateBox("Removed " + RawFileName.ToString + " in thread ID " + Thread.CurrentThread.ManagedThreadId.ToString)
  126. End Sub
  127.  
  128. Private Sub Changed(ByVal source As Object, ByVal e As FileSystemEventArgs)
  129. If AccessEntries.Contains(e.Name) Then
  130. UpdateBox("Ignoring a " + e.ChangeType.ToString + " notification for " + e.Name + " in thread ID " + Thread.CurrentThread.ManagedThreadId.ToString)
  131. Return
  132. End If
  133. Dim AccessTimerThread As Thread
  134.  
  135. AccessEntries.Add(e.Name)
  136. UpdateBox("Adding " + e.Name + " to the collection and starting the watch thread.")
  137. AccessTimerThread = New Thread(AddressOf AccessEntryRemovalTimer)
  138. AccessTimerThread.IsBackground = True
  139. AccessTimerThread.Start(e.Name)
  140.  
  141. End Sub
  142.  
  143. Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  144. tbMonitor.ScrollBars = ScrollBars.Both
  145. AccessEntries = New List(Of String)
  146. fw = New FileSystemWatcher
  147. fw.Path = "C:temp"
  148. fw.NotifyFilter = NotifyFilters.LastWrite Or NotifyFilters.LastAccess Or NotifyFilters.FileName
  149. AddHandler fw.Changed, AddressOf Changed
  150. AddHandler fw.Created, AddressOf Changed
  151. AddHandler fw.Renamed, AddressOf Changed
  152. fw.EnableRaisingEvents = True
  153. End Sub
  154.  
  155. Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
  156. fw.EnableRaisingEvents = False
  157. RemoveHandler fw.Changed, AddressOf Changed
  158. RemoveHandler fw.Created, AddressOf Changed
  159. RemoveHandler fw.Renamed, AddressOf Changed
  160. fw.Dispose()
  161. End Sub
  162.  
  163. public class FileChangeMonitor
  164. {
  165. private FileSystemWatcher _fsw;
  166. DateTime _lastEventTime;
  167.  
  168. public event FileSystemEventHandler Changed;
  169.  
  170. public FileChangeMonitor(string path, string filter)
  171. {
  172. _fsw = new FileSystemWatcher(path, filter);
  173. _fsw.Changed += new FileSystemEventHandler(_fsw_Changed);
  174. _fsw.EnableRaisingEvents = true;
  175. _fsw.NotifyFilter = NotifyFilters.LastWrite;
  176. _fsw.IncludeSubdirectories = false;
  177. }
  178.  
  179. private void _fsw_Changed(object sender, FileSystemEventArgs e)
  180. {
  181. // Fix the FindFirstChangeNotification() double-call bug
  182. if (DateTime.Now.Subtract(_lastEventTime).TotalMilliseconds > 100)
  183. {
  184. _lastEventTime = DateTime.Now;
  185. if (this.Changed != null)
  186. this.Changed(sender, e); // Bubble the event
  187. }
  188. }
  189. }
  190.  
  191. FileChangeMonitor fcm = new FileChangeMonitor(path, filter);
  192. fsm.Changed += new FileSystemEventHandler(fsm_Changed);
  193. ...
  194.  
  195. // Class level variable
  196. bool m_FileSystemWatcherIsMessy = true;
  197.  
  198. // inside call back
  199. if (m_FileSystemWatcherIsMessy) {
  200. m_FileSystemWatcherIsMessy = false;
  201. return;
  202. } else {
  203. m_FileSystemWatcherIsMessy = true;
  204. }
Add Comment
Please, Sign In to add comment