44
55namespace FileWatcherEx ;
66
7+ /// <summary>
8+ /// A wrapper of <see cref="FileSystemWatcher"/> to standardize the events
9+ /// and avoid false change notifications.
10+ /// </summary>
711public class FileSystemWatcherEx : IDisposable
812{
913
1014 #region Private Properties
1115
12- private Thread _thread ;
13- private EventProcessor _processor ;
14- private BlockingCollection < FileChangedEvent > _fileEventQueue = new ( ) ;
16+ private Thread ? _thread ;
17+ private EventProcessor ? _processor ;
18+ private readonly BlockingCollection < FileChangedEvent > _fileEventQueue = new ( ) ;
1519
16- private FileWatcher _watcher = new ( ) ;
17- private FileSystemWatcher _fsw = new ( ) ;
20+ private FileWatcher ? _watcher ;
21+ private FileSystemWatcher ? _fsw ;
1822
1923 // Define the cancellation token.
20- private CancellationTokenSource _cancelSource = new ( ) ;
24+ private readonly CancellationTokenSource _cancelSource = new ( ) ;
2125
2226 #endregion
2327
@@ -26,26 +30,23 @@ public class FileSystemWatcherEx : IDisposable
2630 #region Public Properties
2731
2832 /// <summary>
29- /// Folder path to watch
33+ /// Gets or sets the path of the directory to watch.
3034 /// </summary>
3135 public string FolderPath { get ; set ; } = "" ;
3236
3337
3438 /// <summary>
35- /// The collection of all the filters used to determine what files are monitored in a directory.
39+ /// Gets the collection of all the filters used to determine what files are monitored in a directory.
3640 /// </summary>
3741 public System . Collections . ObjectModel . Collection < string > Filters { get ; } = new ( ) ;
3842
3943
4044 /// <summary>
41- /// Filter string used for determining what files are monitored in a directory
45+ /// Gets or sets the filter string used to determine what files are monitored in a directory.
4246 /// </summary>
4347 public string Filter
4448 {
45- get
46- {
47- return Filters . Count == 0 ? "*" : Filters [ 0 ] ;
48- }
49+ get => Filters . Count == 0 ? "*" : Filters [ 0 ] ;
4950 set
5051 {
5152 Filters . Clear ( ) ;
@@ -55,7 +56,11 @@ public string Filter
5556
5657
5758 /// <summary>
58- /// Gets, sets the type of changes to watch for
59+ /// Gets or sets the type of changes to watch for.
60+ /// The default is the bitwise OR combination of
61+ /// <see cref="NotifyFilters.LastWrite"/>,
62+ /// <see cref="NotifyFilters.FileName"/>,
63+ /// and <see cref="NotifyFilters.DirectoryName"/>.
5964 /// </summary>
6065 public NotifyFilters NotifyFilter { get ; set ; } = NotifyFilters . LastWrite | NotifyFilters . FileName | NotifyFilters . DirectoryName ;
6166
@@ -69,38 +74,64 @@ public string Filter
6974 /// <summary>
7075 /// Gets or sets the object used to marshal the event handler calls issued as a result of a directory change.
7176 /// </summary>
72- public ISynchronizeInvoke SynchronizingObject { get ; set ; }
77+ public ISynchronizeInvoke ? SynchronizingObject { get ; set ; }
7378
7479 #endregion
7580
7681
7782
7883 #region Public Events
79- public delegate void DelegateOnChanged ( object sender , FileChangedEvent e ) ;
80- public event DelegateOnChanged OnChanged ;
8184
82- public delegate void DelegateOnDeleted ( object sender , FileChangedEvent e ) ;
83- public event DelegateOnDeleted OnDeleted ;
85+ /// <summary>
86+ /// Occurs when a file or directory in the specified
87+ /// <see cref="FolderPath"/> is changed.
88+ /// </summary>
89+ public event DelegateOnChanged ? OnChanged ;
90+ public delegate void DelegateOnChanged ( object ? sender , FileChangedEvent e ) ;
91+
92+
93+ /// <summary>
94+ /// Occurs when a file or directory in the specified
95+ /// <see cref="FolderPath"/> is deleted.
96+ /// </summary>
97+ public event DelegateOnDeleted ? OnDeleted ;
98+ public delegate void DelegateOnDeleted ( object ? sender , FileChangedEvent e ) ;
8499
85- public delegate void DelegateOnCreated ( object sender , FileChangedEvent e ) ;
86- public event DelegateOnCreated OnCreated ;
87100
88- public delegate void DelegateOnRenamed ( object sender , FileChangedEvent e ) ;
89- public event DelegateOnRenamed OnRenamed ;
101+ /// <summary>
102+ /// Occurs when a file or directory in the specified
103+ /// <see cref="FolderPath"/> is created.
104+ /// </summary>
105+ public event DelegateOnCreated ? OnCreated ;
106+ public delegate void DelegateOnCreated ( object ? sender , FileChangedEvent e ) ;
107+
108+
109+ /// <summary>
110+ /// Occurs when a file or directory in the specified
111+ /// <see cref="FolderPath"/> is renamed.
112+ /// </summary>
113+ public event DelegateOnRenamed ? OnRenamed ;
114+ public delegate void DelegateOnRenamed ( object ? sender , FileChangedEvent e ) ;
115+
116+
117+ /// <summary>
118+ /// Occurs when the instance of <see cref="FileSystemWatcherEx"/> is unable to continue
119+ /// monitoring changes or when the internal buffer overflows.
120+ /// </summary>
121+ public event DelegateOnError ? OnError ;
122+ public delegate void DelegateOnError ( object ? sender , ErrorEventArgs e ) ;
90123
91- public delegate void DelegateOnError ( object sender , ErrorEventArgs e ) ;
92- public event DelegateOnError OnError ;
93124 #endregion
94125
95126
96127
97128 /// <summary>
98- /// Initialize new instance of FileWatcherEx
129+ /// Initialize new instance of <see cref="FileSystemWatcherEx"/>
99130 /// </summary>
100- /// <param name="folder "></param>
101- public FileSystemWatcherEx ( string folder = "" )
131+ /// <param name="folderPath "></param>
132+ public FileSystemWatcherEx ( string folderPath = "" )
102133 {
103- FolderPath = folder ;
134+ FolderPath = folderPath ;
104135 }
105136
106137
@@ -120,7 +151,7 @@ public void Start()
120151
121152 InvokeChangedEvent ( SynchronizingObject , e ) ;
122153
123- void InvokeChangedEvent ( object sender , FileChangedEvent fileEvent )
154+ void InvokeChangedEvent ( object ? sender , FileChangedEvent fileEvent )
124155 {
125156 if ( SynchronizingObject != null && SynchronizingObject . InvokeRequired )
126157 {
@@ -139,7 +170,7 @@ void InvokeChangedEvent(object sender, FileChangedEvent fileEvent)
139170
140171 InvokeCreatedEvent ( SynchronizingObject , e ) ;
141172
142- void InvokeCreatedEvent ( object sender , FileChangedEvent fileEvent )
173+ void InvokeCreatedEvent ( object ? sender , FileChangedEvent fileEvent )
143174 {
144175 if ( SynchronizingObject != null && SynchronizingObject . InvokeRequired )
145176 {
@@ -158,7 +189,7 @@ void InvokeCreatedEvent(object sender, FileChangedEvent fileEvent)
158189
159190 InvokeDeletedEvent ( SynchronizingObject , e ) ;
160191
161- void InvokeDeletedEvent ( object sender , FileChangedEvent fileEvent )
192+ void InvokeDeletedEvent ( object ? sender , FileChangedEvent fileEvent )
162193 {
163194 if ( SynchronizingObject != null && SynchronizingObject . InvokeRequired )
164195 {
@@ -177,7 +208,7 @@ void InvokeDeletedEvent(object sender, FileChangedEvent fileEvent)
177208
178209 InvokeRenamedEvent ( SynchronizingObject , e ) ;
179210
180- void InvokeRenamedEvent ( object sender , FileChangedEvent fileEvent )
211+ void InvokeRenamedEvent ( object ? sender , FileChangedEvent fileEvent )
181212 {
182213 if ( SynchronizingObject != null && SynchronizingObject . InvokeRequired )
183214 {
@@ -244,25 +275,6 @@ void onError(ErrorEventArgs e)
244275 _fsw . EnableRaisingEvents = true ;
245276 }
246277
247- private void Thread_DoingWork ( CancellationToken cancelToken )
248- {
249- while ( true )
250- {
251- if ( cancelToken . IsCancellationRequested )
252- return ;
253-
254- try
255- {
256- var e = _fileEventQueue . Take ( cancelToken ) ;
257- _processor . ProcessEvent ( e ) ;
258- }
259- catch ( OperationCanceledException )
260- {
261- return ;
262- }
263- }
264- }
265-
266278
267279 /// <summary>
268280 /// Stop watching files
@@ -284,7 +296,6 @@ public void Stop()
284296 }
285297
286298
287-
288299 /// <summary>
289300 /// Dispose the FileWatcherEx instance
290301 /// </summary>
@@ -293,7 +304,30 @@ public void Dispose()
293304 if ( _fsw != null )
294305 {
295306 _fsw . Dispose ( ) ;
307+ GC . SuppressFinalize ( this ) ;
296308 }
297309 }
298310
311+
312+
313+ private void Thread_DoingWork ( CancellationToken cancelToken )
314+ {
315+ while ( true )
316+ {
317+ if ( cancelToken . IsCancellationRequested )
318+ return ;
319+
320+ try
321+ {
322+ var e = _fileEventQueue . Take ( cancelToken ) ;
323+ _processor ? . ProcessEvent ( e ) ;
324+ }
325+ catch ( OperationCanceledException )
326+ {
327+ return ;
328+ }
329+ }
330+ }
331+
332+
299333}
0 commit comments