Click here to Skip to main content
16,016,623 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am having trouble accessing a FileSystemWatcher from another method.

C#
public static void watch(string path)
{
    FileSystemWatcher watcher = new FileSystemWatcher();

    watcher.Path = path;
    watcher.NotifyFilter = NotifyFilters.Attributes |
                   NotifyFilters.CreationTime |
                   NotifyFilters.DirectoryName |
                   NotifyFilters.FileName |
                   NotifyFilters.LastAccess |
                   NotifyFilters.LastWrite |
                   NotifyFilters.Security |
                   NotifyFilters.Size;
    watcher.Filter = "*.*";
    watcher.IncludeSubdirectories = true;
    watcher.Changed += new FileSystemEventHandler(OnChanged);
    watcher.Created += new FileSystemEventHandler(OnChanged);
    watcher.Deleted += new FileSystemEventHandler(OnChanged);
    watcher.Renamed += new RenamedEventHandler(OnChanged);
    watcher.EnableRaisingEvents = true;
}

private static void OnChanged(object sender, FileSystemEventArgs e)
{
    // The reason for having this try block (and EnableRaisingEvents toggling)
    // is to solve a known problem with FileSystemWatcher, in which the event
    // is fired twice.

    try
    {
        MessageBox.Show("File changed.");

        watcher.EnableRaisingEvents = false; // Error: The name 'watcher' does
                                            // not exist in the current context
    }
    finally
    {
        watcher.EnableRaisingEvents = true; // Error: The name 'watcher' does
                                           // not exist in the current context
    }
}


I want to change the EnableRaisingEvents property.

I can't do that because of the scope problem. Normally what I would do is declare the FileSystemWatcher somewhere with a bigger scope, but I can't do that here because a new one must be created every time I run the method.

So, how can I change the property of an object from a different method?

PS: I have searched around, and tried different things but ultimately nothing worked.

EDIT: Just to clarify, I MUST keep the FileSystemWatcher declaration INSIDE the method (as opposed to giving it a bigger scope, thus allowing it to be modified by another method). The reason for this is that I need a new one to be created every time I run the method.
Posted
Comments
PIEBALDconsult 6-May-14 20:05pm    
"I need a new one to be created every time I run the method"
You can still do that even if you declare it outside the method.
(It still sounds like a weird requirement though.)
[no name] 6-May-14 21:10pm    
"ultimately nothing worked", and that is as it should be.
Matt T Heffron 7-May-14 13:02pm    
Did my Solution 1 help?
If so, please formally "Accept" the solution.

Looking at your code again, I'm wondering what keeps the FileSystemWatcher that is created in the watch() method from being garbage collected away? There doesn't seem to be anything that will reference it after the end of watch(). You might need to keep some collection of all such created FileSystemWatchers in a static field/property of this class.
BeginnerForLife 7-May-14 14:16pm    
I have accepted your solution. Thank you very much, it worked flawlessly.

Sorry for the delay, I was not able to review your solution until just before this reply.

1 solution

I'm pretty sure that the FileSystemWatcher created in the watch method will be the value of the sender parameter of the OnChanged method.
In that case, it should be pretty simple:
C#
private static void OnChanged(object sender, FileSystemEventArgs e)
{
    FileSystemWatcher watcher = sender as FileSystemWatcher;
    if (watcher == null)      // sender isn't a FileSystemWatcher
      return;                 // quit while we're behind! :-)

    // The reason for having this try block (and EnableRaisingEvents toggling)
    // is to solve a known problem with FileSystemWatcher, in which the event
    // is fired twice.

    try
    {
        MessageBox.Show("File changed.");

        watcher.EnableRaisingEvents = false; // Error: The name 'watcher' does
                                             // not exist in the current context
    }
    finally
    {
        watcher.EnableRaisingEvents = true; // Error: The name 'watcher' does
                                            // not exist in the current context
    }
}
 
Share this answer
 
Comments
PIEBALDconsult 7-May-14 0:12am    
I'm concerned that these watchers will never be garbage collected and could lead to an out-of-memory situation.<br>
I forget what I had read about event handlers causing memory leaks many moons ago.
Along with disabling, the code should probably detach the handlers.
Sergey Alexandrovich Kryukov 7-May-14 0:54am    
This is not such a serious problem. Normally, detaching event handler is a bad thing; a need in it is often a result of bad architecture. If handlers are anonymous, there is nothing to detach.

The leak happens when you add handlers again and again. The publisher of event is holding reference to the subscribers, preventing their finalization. If a handler is added fixed number of times for the lifetime of the publisher object, everything will be free to dispose when the publisher is disposed. No problem.

This memory leak happens as a result of pretty stupid code design. Imagine that you keep a list of objects and add the reference every time you create an object and forget to remove them when the objects are needed. This will effectively keep those objects reachable and hence prevent their finalization. Stupid code can screw up everything.

—SA
Sergey Alexandrovich Kryukov 7-May-14 0:54am    
My 5; And I tried to dismiss the concern explained above.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900