2007-01-07

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. You can read a discussion about this on Channel 9, in this thread. 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 class FileCreationWatcher : IDisposable
{
  FileSystemWatcher fWatcher;

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

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

  void OnFileCreated(object sender, FileSystemEventArgs e)
  {
    FileInfo lFile = new FileInfo(e.FullPath);
    if (lFile.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
            lFile.OpenRead().Close();
            break;
          }
          catch(IOException)
          {
            // if the file is still locked, keep trying
            continue;
          }
        }

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

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

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

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

  public event FileSystemEventHandler Created;

  #region IDisposable Members

  public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }

  ~FileCreationWatcher() { Dispose(false); }

  protected virtual void Dispose(bool disposing)
  {
    if (disposing)
      fWatcher.Dispose();
  }

  #endregion
}
Technorati tags: , .

4 comments:

Anonymous said...

Hi Tommy

Are you aware of a way to implement this class on Windows Mobile 5?

Tommy Carlier said...

OpenNETCF has an implementation of FileSystemWatcher for the Compact Framework.

Volem said...

Thanks for the post. It works fine for now :)

Anonymous said...

Thanks a lot. Saved my day