How to Use FileSystemWatcher Instead of Polling - Source Code

by Larry Spencer Sunday, January 27, 2013 4:00 PM

The last four posts have presented an engineering project for a seemingly simple task: watching a directory for new files so another task can process them. I've packaged the source so you can download it here: (208.71 kb) [updated 25-Mar-2013 with thanks to Gavin Aiken].

The files include

  • WatchedFileCollection, the class that started this series. It wraps a FileSystemWatcher and presents its events in an IEnumerable<string>. In the original post, WatchedFileCollection contained the code for the next three classes. I have since decided that each is useful on its own, so I made separate classes out of them.
  • CancellableQueue, encapsulating a ConcurrentQueue from which items can be dequeued subject to a CancellationToken.
  • CancellableFileSystemEventQueue, a CancellableQueue specialized for the events from a FileSystemWatcher.
  • CreatedFileCollection, derived from WatchedFileCollection to present only the FileSystemWatcher's Created events. 
  • ChangedFileCollection, also derived from WatchedFileCollection but for file-change events reported by the FileSystemWatcher. I did not present this class in the series, but it's here as a bonus.
  • TimedDistinctCollection, which I discussed in the second post, How to Filter Long-Running IEnumerables for Distinct Objects.
  • ReadyItemCollection, discussed in the third post, How to Apply a Gate to An IEnumerable<T>. It is an IEnumerable<T> that presents items from an input IEnumerable<T> only as they are "ready".
  • ReadyFileCollection, derived from ReadyItemCollection and specialized for files, as discussed in the fourth post.

The ZIP also includes a complete unit-testing project.

One final note before we leave this series. Here is an example of putting all the classes together to create an IEnumerable pipe that yields files matching "*.txt" from a source directory, waiting for each one to have had no activity for at least 2 minutes, and retaining a 5-minute memory of file names for the purpose of detecting duplicates.


string sourceDir = @"C:\Some\Directory";
string filePattern = "*.txt";
var quiesceTime = TimeSpan.FromMinutes(2);
var dupeTime = TimeSpan.FromMinutes(5);

var files =
    new ReadyFileCollection(
        new TimedDistinctCollection<string>(
            new CreatedFileCollection(cts.Token, sourceDir, filePattern),
            fileName => fileName),

foreach (var file in files)
    // Do something

Tags: , ,

All | Talks

About the Author

Larry Spencer

Larry Spencer develops software with the Microsoft .NET Framework for ScerIS, a document-management company in Sudbury, MA.