I want to use FileSystemWatcher to monitor a directory and its subdirectories for relocatable files. And then I want to call the code when all the files have been moved. But I do not know how to do this. My code, as it is, will run every time a file is moved, and if the user moves several files at once, I only want it to run once for all files. So basically I want to create a list, and as soon as the movement of all files is complete, I want to make stuff in this list ...
Here is the code:
class Monitor { private List<string> _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!"); } }
UPDATE: Trying to use Chris code, but it doesn't work (see my comment in Chris's answer):
class Monitor { private List<string> _filePaths; private Timer _notificationTimer; private FileSystemWatcher _fsw; public Monitor(string path) { _notificationTimer = new Timer(); _notificationTimer.Elapsed += notificationTimer_Elapsed;
UPDATE 2:
Tried this according to Anders:
public class FileListEventArgs : EventArgs { public List<string> FileList { get; set; } } public class Monitor { private List<string> 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<string>(); 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<string> list = new List<string>(); 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) {
I had to move the event trigger to a finally expression, and this works. I do not know if there is a reason why I do not want to do this?
source share