FileCreationWatcher

A few weeks ago, I received an e-mail from someone who asked me if I could give more details about a class I created at work, that is essentially a wrapper around the FileSystemWatcher class, and that detects the creation of files more reliably. I sent him an e-mail back, with a simplified version of the wrapper class, and because I think this could also be useful for other people, I decided to post it here.

public sealed class FileCreationWatcher : IDisposable
{
  private FileSystemWatcher _watcher;

  public FileCreationWatcher(string path, string filter)
  {
    Initialize(path, filter);
  }

  private void Initialize(string path, string filter)
  {
    _watcher = new FileSystemWatcher(path, filter);
    _watcher.Created += OnFileCreated;
    _watcher.Error += OnError;
  }

  private void OnFileCreated(object sender, FileSystemEventArgs e)
  {
    FileInfo file = new FileInfo(e.FullPath);
    if (file.Exists)
    {
      // schedule the processing on a different thread
      ThreadPool.QueueUserWorkItem(delegate
      {
        while(true)
        {
          // wait 100 milliseconds between attempts to read
          Thread.Sleep(TimeSpan.FromMilliseconds(100));
          try
          {
            // try to open the file
            file.OpenRead().Close();
            break;
          }
          catch(IOException)
          {
            // if the file is still locked, keep trying
            continue;
          }
        }

        // the file can be opened successfully: raise the event
        FileSystemEventHandler handler = Created;
        if (handler != null)
        {
          handler(this, e);
        }
      });
    }
  }

  private void OnError(object sender, ErrorEventArgs e)
  {
    // when an error occurs, the current FileSystemWatcher is disposed,
    // and a new one is created
    
    string path = _watcher.Path;
    string filter = _watcher.Filter;
    _watcher.Dispose();
    Initialize(path, filter);
  }

  public void Start()
  {
    _watcher.EnableRaisingEvents = true;
  }

  public void Stop()
  {
    _watcher.EnableRaisingEvents = false;
  }

  public event FileSystemEventHandler Created;

  public void Dispose()
  {
    _watcher.Dispose();
  }
}