Like others (FileSystemWatcher Changed event is raised twice) I am facing the problem that events of filesystemwatcher are raised twice. I require to catch all non-duplicate events of watcher in real time. I came up with this. So, I want to know if it will be efficient/over-kill/buggy to use this class.
class ModifiedFileSystemWatcher:FileSystemWatcher
{
public new event RenamedEventHandler Renamed;
public new event FileSystemEventHandler Deleted;
public new event FileSystemEventHandler Created;
public new event FileSystemEventHandler Changed;
class BooleanWrapper{
public bool value { get; set; }
}
//stores refrences of previously fired events with same file source
Dictionary<string, BooleanWrapper> raiseEvent = new Dictionary<string, BooleanWrapper>();
public int WaitingTime { get; set; } //waiting time, any new event raised with same file source will discard previous one
public ModifiedFileSystemWatcher(string filename="", string filter="*.*"):base(filename,filter)
{
base.Changed += ModifiedFileSystemWatcher_Changed;
base.Created += ModifiedFileSystemWatcher_Created;
base.Deleted += ModifiedFileSystemWatcher_Deleted;
base.Renamed += ModifiedFileSystemWatcher_Renamed;
WaitingTime = 100;
}
void PreventDuplicate(FileSystemEventHandler _event, FileSystemEventArgs e)
{
if (_event != null)
{
//create a reference
BooleanWrapper w = new BooleanWrapper() { value = true }; //this event will be fired
BooleanWrapper t; //tmp
if (raiseEvent.TryGetValue(e.FullPath, out t))
{
//a previous event occurred which is waiting [delayed by WaitingTime]
t.value = false; //set its reference to false; that event will be skipped
t = w;//store current reference in dictionary
}
else raiseEvent[e.FullPath] = w; //no previous event, store our reference
//Wait on a separate thread...
System.Threading.ThreadPool.QueueUserWorkItem(delegate
{
System.Threading.Thread.Sleep(WaitingTime);
if (w.value) //if we are still allowed to raise event
{
_event(this, e);
raiseEvent.Remove(e.FullPath);//remove instance from dictionary
}
}, null);
}
}
//Same as above with different event
void ModifiedFileSystemWatcher_Renamed(object sender, RenamedEventArgs e)
{
if (Renamed != null)
{
BooleanWrapper w = new BooleanWrapper() { value = true };
BooleanWrapper t;
if (raiseEvent.TryGetValue(e.FullPath, out t))
{
t.value = false;
t = w;
}
else raiseEvent[e.FullPath] = w;
System.Threading.Thread.Sleep(WaitingTime);
if (w.value)
{
Renamed(this, e);
raiseEvent.Remove(e.FullPath);
}
}
}
void ModifiedFileSystemWatcher_Deleted(object sender, FileSystemEventArgs e)
{
PreventDuplicate(Deleted, e);
}
void ModifiedFileSystemWatcher_Created(object sender, FileSystemEventArgs e)
{
PreventDuplicate(Created, e);
}
void ModifiedFileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
PreventDuplicate(Changed, e);
}
}