title: Using FileSystemWatcher with multiple files
body: <p>I want to use FileSystemWatcher to monitor a directory and its subdirectories for files that are moved. And then I want to trigger some code when all the files have been moved. But I don't know how. My code as is will trigger each time a file is moved, and if a user moves several files at once I only want it to trigger once for all files. So basically I want to create a list, and once the moving of all files is done I want to do stuff to that list...</p>
  
  <p>Here's the code:</p>
  
  <pre><code>class Monitor
  {
      private List&lt;string&gt; _filePaths;  
      public void CreateWatcher(string path)
      {
          FileSystemWatcher watcher = new FileSystemWatcher();
  
          watcher.Filter = "*.*";
  
          watcher.Created += new
          FileSystemEventHandler(watcher_FileCreated);
  
          watcher.Path = path;
          watcher.IncludeSubdirectories = true;
  
          watcher.EnableRaisingEvents = true;
      }
  
      void watcher_FileCreated(object sender, FileSystemEventArgs e)
      {
          _filePaths.Add(e.FullPath);
          Console.WriteLine("Files have been created or moved!");
      }
  
  }
  </code></pre>
  
  <p>UPDATE: Trying to use Chris's code, but it doesn't work (see my comment at Chris's answer):</p>
  
  <pre><code>class Monitor
      {
          private List&lt;string&gt; _filePaths;
          private Timer _notificationTimer;
          private FileSystemWatcher _fsw;
          public Monitor(string path)
          {
              _notificationTimer = new Timer();
              _notificationTimer.Elapsed += notificationTimer_Elapsed;
              // CooldownSeconds is the number of seconds the Timer is 'extended' each time a file is added.
              // I found it convenient to put this value in an app config file.
              int CooldownSeconds = 1;
              _notificationTimer.Interval = CooldownSeconds * 1000;
  
              _fsw = new FileSystemWatcher();
              _fsw.Path = path;
              _fsw.IncludeSubdirectories = true;
              _fsw.EnableRaisingEvents = true;
  
              // Set up the particulars of your FileSystemWatcher.
              _fsw.Created += fsw_Created;
          }
  
          private void notificationTimer_Elapsed(object sender, ElapsedEventArgs e)
          {
              //
              // Do what you want to do with your List of files.
              //
              Console.Write("Done");
              // Stop the timer and wait for the next batch of files.            
              _notificationTimer.Stop();
              // Clear your file List.
              _filePaths = new List&lt;string&gt;();
          }
  
  
          // Fires when a file is created.
          private void fsw_Created(object sender, FileSystemEventArgs e)
          {
              // Add to our List of files.
              _filePaths.Add(e.Name);
  
              // 'Reset' timer.
              _notificationTimer.Stop();
              _notificationTimer.Start();
          }
  
  
      }
  </code></pre>
  
  <p>UPDATE 2:</p>
  
  <p>Tried this according to Anders's answer:</p>
  
  <pre><code>public class FileListEventArgs : EventArgs
  {
      public List&lt;string&gt; FileList { get; set; }
  }
  
  public class Monitor
  {
      private List&lt;string&gt; filePaths;
      private ReaderWriterLockSlim rwlock;
      private Timer processTimer;
      public event EventHandler FileListCreated;
  
  
      public void OnFileListCreated(FileListEventArgs e)
      {
          if (FileListCreated != null)
              FileListCreated(this, e);
      }
  
      public Monitor(string path)
      {
          filePaths = new List&lt;string&gt;();
  
          rwlock = new ReaderWriterLockSlim();
  
          FileSystemWatcher watcher = new FileSystemWatcher();
          watcher.Filter = "*.*";
          watcher.Created += watcher_FileCreated;
  
          watcher.Path = path;
          watcher.IncludeSubdirectories = true;
          watcher.EnableRaisingEvents = true;
      }
  
      private void ProcessQueue()
      {
          List&lt;string&gt; list = new List&lt;string&gt;();
          try
          {
              Console.WriteLine("Processing queue, " + filePaths.Count + " files created:");
              rwlock.EnterReadLock();
  
          }
          finally
          {
              if (processTimer != null)
              {
                  processTimer.Stop();
                  processTimer.Dispose();
                  processTimer = null;
                  OnFileListCreated(new FileListEventArgs { FileList = filePaths });
                  filePaths.Clear();
              }
              rwlock.ExitReadLock();
          }
      }
  
      void watcher_FileCreated(object sender, FileSystemEventArgs e)
      {
          try
          {
              rwlock.EnterWriteLock();
              filePaths.Add(e.FullPath);
  
              if (processTimer == null)
              {
                  // First file, start timer.
                  processTimer = new Timer(2000);
                  processTimer.Elapsed += (o, ee) =&gt; ProcessQueue();
                  processTimer.Start();
              }
              else
              {
                  // Subsequent file, reset timer. 
                  processTimer.Stop();
                  processTimer.Start();
              }
  
          }
          finally
          {
              rwlock.ExitWriteLock();
          }
      }
  </code></pre>
  
  <p>I had to move the event trigger into the finally statement, and that works. I don't know if there is some reason I wouldn't want to do that?</p>