Reputation: 65
Thanks for any help on this..
I am trying to write a little FileWatcher app that monitors a local directory and copies any changes across to another local directory. I have used the FileSystemWatcher class in .Net and on my btnStart click I run four threads, each with there own FileSysWatcher instance, watching for different change types. So the first i want to look for is the created event.
new Thread(Created).Start();
then i have:
void Created()
{
FileSystemWatcher Watcher2 = new FileSystemWatcher();
Watcher2.Path = txtBxDirToWatch.Text;
Watcher2.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.DirectoryName;
//watch all files in the path
Watcher2.Filter = "*.*";
//dont watch sub dir as default
Watcher2.IncludeSubdirectories = false;
if (chkBxIncSub.Checked)
{
Watcher2.IncludeSubdirectories = true;
}
Watcher2.Created += new FileSystemEventHandler(OnCreated);
Watcher2.EnableRaisingEvents = true;
}
all I want this to do is copy any changes to a hard coded local path but I cant get any results. here is where I handled the event
public static void OnCreated(object source, FileSystemEventArgs e)
{
//combine new path into a string
string created = Path.Combine(@"C:\WatcherChanges", e.Name);
File.Create(created);
}
Upvotes: 1
Views: 9728
Reputation: 7202
There is no reason to create the watchers in separate threads.
They will come back to you on thread pool threads when something on your watched directory happens. When they do - you do your job on the thread pool thread if it's not UI related. If it is - you have to do control.Invoke or post/send to the Gui thread using it's SynchronizationContext.
And yes -as the others have already said - don't let your watchers get GC'd.
Upvotes: 0
Reputation: 46183
Your thread is exiting right after you tell the watcher to enable raising events. There is nothing in the Create
method to keep the thread running. At the end of the Create
method the FileSystemWatcher
goes out of scope and the thread exits. It will never see any events.
There are a number of ways to get the thread to wait. Here is a simple one.
public class Watcher
{
private ManualResetEvent resetEvent = new ManualResetEvent(false);
public ManualResetEvent ResetEvent { get { return resetEvent; }
void Created()
{
FileSystemWatcher Watcher2 = new FileSystemWatcher();
Watcher2.Path = txtBxDirToWatch.Text;
Watcher2.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.DirectoryName;
//watch all files in the path
Watcher2.Filter = "*.*";
//dont watch sub dir as default
Watcher2.IncludeSubdirectories = false;
if (chkBxIncSub.Checked)
{
Watcher2.IncludeSubdirectories = true;
}
Watcher2.Created += new FileSystemEventHandler(OnCreated);
Watcher2.EnableRaisingEvents = true;
resetEvent.WaitOne();
}
Then change the method that calls Thread.Start
to something like
Watcher watcher = new Watcher();
new Thread(watcher.Created).Start();
and when you want to stop watching
watcher.ResetEvent.Set();
Have you looked at RoboCopy? It will do this for you.
Upvotes: 0
Reputation: 16981
In your code thread finished and then GC collect and release Watcher.
Don't use thread for watchers or "hang" thread:
new Thread(Created){IsBackground = true}.Start();
void Created()
{
...
Thread.CurrentThread.Join();
}
Upvotes: 1