Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileSystemWatcher Dispose call hangs

We just started running in to an odd problem with a FileSystemWatcher where the call to Dispose() appears to be hanging. This is code that has been working without any problems for a while but we just upgraded to .NET3.5 SP1 so I'm trying to find out if anyone else has seen this behavior. Here is the code that creates the FileSystemWatcher:

if (this.fileWatcher == null)
{
   this.fileWatcher = new FileSystemWatcher();
}
this.fileWatcher.BeginInit();
this.fileWatcher.IncludeSubdirectories = true;
this.fileWatcher.Path = project.Directory;
this.fileWatcher.EnableRaisingEvents = true;
this.fileWatcher.NotifyFilter = NotifyFilters.Attributes;
this.fileWatcher.Changed += delegate(object s, FileSystemEventArgs args)
{
   FileWatcherFileChanged(args);
};
this.fileWatcher.EndInit();

The way this is being used is to update the state image of a TreeNode object (adjusted slightly to remove business specific information):

private void FileWatcherFileChanged(FileSystemEventArgs args)
{
   if (this.TreeView != null)
   {
      if (this.TreeView.InvokeRequired)
      {
         FileWatcherFileChangedCallback d = new FileWatcherFileChangedCallback(FileWatcherFileChanged);
         this.TreeView.Invoke(d, new object[]
      {
         args
      });
      }
      else
      {
         switch (args.ChangeType)
         {
            case WatcherChangeTypes.Changed:
               if (String.CompareOrdinal(this.project.FullName, args.FullPath) == 0)
               {
                  this.StateImageKey = GetStateImageKey();
               }
               else
               {
                  projectItemTreeNode.StateImageKey = GetStateImageKey();
               }
               break;
         }
      }
   }
}

Is there something we're missing or is this an anomoly from .NET3.5 SP1?

like image 539
Scott Dorman Avatar asked Sep 16 '08 14:09

Scott Dorman


3 Answers

Just a thought... Any chance there's a deadlock issue here?

You're calling TreeView.Invoke, which is a blocking call. If a filesystem change happens just as you're clicking whatever button causes the FileSystemWatcher.Dispose() call, your FileWatcherFileChanged method will get called on a background thread and call TreeView.Invoke, which will block until your form thread can process the Invoke request. However, your form thread would be calling FileSystemWatcher.Dispose(), which probably doesn't return until all pending change requests are processed.

Try changing the .Invoke to .BeginInvoke and see if that helps. That may help point you in the right direction.

Of course, it could also be a .NET 3.5SP1 issue. I'm just speculating here based on the code you provided.

like image 137
Jonathan Rupp Avatar answered Nov 17 '22 08:11

Jonathan Rupp


Scott, we've occasionally seen issues with control.Invoke in .NET 2. Try switching to control.BeginInvoke and see if that helps.

Doing that will allow the FileSystemWatcher thread to return immediately. I suspect your issue is somehow that the control.Invoke is blocking, thus causing the FileSystemWatcher to freeze upon dispose.

like image 22
Judah Gabriel Himango Avatar answered Nov 17 '22 08:11

Judah Gabriel Himango


We are also having this issue. Our application runs on .Net 2.0 but is compiled by VS 2008 SP1. I have .NET 3.5 SP1 installed as well. I've got no idea why this happens either, it doesn't look like a deadlock issue on our end as no other threads are running at this point (it is during application shutdown).

like image 43
Jamie Penney Avatar answered Nov 17 '22 08:11

Jamie Penney