Liam
Liam

Reputation: 65

FileSystemWatcher on Threads

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

Answers (3)

Ventsyslav Raikov
Ventsyslav Raikov

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

Mike Two
Mike Two

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

Serj-Tm
Serj-Tm

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

Related Questions