11

I'm writing a solution where I use some configuration files that should be editable at runtime. I've been using FileSystemWatcher for this purpose before and never had much issues with it but now it's causing a CTD on the 'rename' event.

This (useless) piece of code will recreate the problem in my setup:

private static int _s_renamed;
private static int _s_created;
private static int _s_errors;

private static void monitorConfiguration(string configRootFolder)
{
    var fsw = new FileSystemWatcher(configRootFolder, ConfigFilePattern)
    {
        NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName,
        IncludeSubdirectories = false
    };
    fsw.Renamed += (sender, args) => ++_s_renamed; // <-- ! CTD efter this one !
    fsw.Created += (sender, args) => ++_s_created;
    fsw.Error += (sender, args) => ++_s_errors; 
    fsw.EnableRaisingEvents = true;
}

The crash comes from FileSystemWatcher it seems. If I set a breakpoint in the event handler for FileSystemWatcher.Renamed it gets hit but the app crashes when I step out of it. If I set a breakpoint in the FileSystemWatcher.Created event handler this does not happen.

Any suggestions?


EDIT 1: I'm running .NET 4 on a Windows 7 x64 (Ultimate) platform I have seen several discussions concerning this type of problems but all has been related to people trying to update UI stuff (which must be done from the main/UI thread) from the event handlers. That's why I just try to increment some counters in the experimental code.

Yuck
  • 49,664
  • 13
  • 105
  • 135
Jonas Rembratt
  • 1,550
  • 3
  • 17
  • 39
  • No, the app crashes to desktop and it seems I cannot catch it. It's a WPF application and I'm catching all unhandled exceptions (Application.DispatcherUnhandledException) but this one isn't caught. – Jonas Rembratt Jan 06 '12 at 19:05
  • What is a CTD and what does it do? – Gabe Jan 06 '12 at 19:08
  • Is there anything in the event viewer? – Steven Evers Jan 06 '12 at 19:09
  • 2
    CTD = "Crash To Desktop" – Jonas Rembratt Jan 06 '12 at 19:13
  • There's nothing in the Event Viewer. At least not under the "Application" node. Should I look anywhere else? – Jonas Rembratt Jan 06 '12 at 19:14
  • It seems that the event handler itself has nothing to do with it. Just to make sure I removed the problematic code line (the one with the comment). When I rename a file the app still CTD's without calling any event handler. – Jonas Rembratt Jan 06 '12 at 19:19
  • Could someone please try and copy the code into a simple WPF app and see if it can be reproduced? Thanks. – Jonas Rembratt Jan 06 '12 at 19:24
  • 4
    I've created WPF project with your code. I've started the watcher in the App's constructor and it's working fine. Win7 x64 (Enterprise). – nemesv Jan 06 '12 at 19:32
  • Thanks nemesv. That hints it could be an environmental issue. – Jonas Rembratt Jan 06 '12 at 19:39
  • I also created a completely new little WPF app and all works ok in that one. So, it's not related to environment after all. Apparently FSW fails for some reason that originates somewhere in my (quite complex) WPF solution. Has anyone else seen this behavior? – Jonas Rembratt Jan 06 '12 at 19:45
  • There are some known memory leaks with `FileSystemWatcher` but I think your problem might be elsewhere. – SomeWritesReserved Jan 06 '12 at 19:47
  • 8
    In WPF, exceptions on the UI thread often cause CTD. When you run in debugger, use break on exceptions to be 100% sure that one isnt being thrown: http://msdn.microsoft.com/en-us/library/d14azbfh.aspx – Chris Shain Jan 06 '12 at 19:48
  • 3
    Chris: Thanks for pointing this out! Write it as an answer and I'll mark it as the solution. I hadn't had the "break on exception" turned on for so long I had forgot that trick. It turned out I had more event handlers elsewhere (for "Renamed") and one of them is failing. Seems the error handling code in `FileSystemWatcher` is inadequate but the problem was in my own code. I'm a bit miffed the debugger didn't break when the exception gets thrown from one of my own event handlers but there you are. Thanks! – Jonas Rembratt Jan 06 '12 at 19:58
  • as an aside. FileSystemWatcher tends to keep running even after it's gone out of scope. Wrap it in a using statement so that you don't end up with hundreds of FileSystemWatcher's running. – deltree Feb 02 '12 at 01:12

4 Answers4

1

Just to clarify:

The problem here was I had more/older consumers of the FileSystemWatcher elsewhere in my system and one of them caused an unhandled exception. The problem is the exception gets thrown in a completely different thread and caused the application to crasch to desktop. The timing fooled me into thinking it was my new consumer that somehow cause the isse but when I followed Chris Shain's advice (see comments in the question entry) to enable break on exceptions (msdn.microsoft.com/en-us/library/d14azbfh.aspx) I immediately found the real culprit.

I would have preferred to credit Chris with the solution but he never re-posted so here it is. Hopefully we've learned something.

Thanks everyone and happy coding

/Jonas

Jonas Rembratt
  • 1,550
  • 3
  • 17
  • 39
0

You may be running into any of these three situations

  1. The directory passed in does not exist and an file io not found is being thrown.
  2. The directory passed in is valid but the process running it does not have access rights
  3. The arguments (sender, args) as passed in, one may be null and your code (since this is an example and we can't see the real code) is not handling the null and throwing an error.
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
0

In .NET you must sync the thread generated by FileSystemWatcher with the UI Thread. For this, the UI controls have a method like: myControl.Invoke(...) for this effect. Any other way to try to sync will have some random effects like crashs, Exceptions, etc.

see here: http://msdn.microsoft.com/en-us/magazine/cc300429.aspx http://weblogs.asp.net/justin_rogers/pages/126345.aspx

hope it helps

Tx3
  • 6,796
  • 4
  • 37
  • 52
José Cruz
  • 35
  • 3
0

Maybe your file or object are in use, I had a similar problem and I resolved it using the following code

private void InitWatch()
{
    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = @"C:\LoQueSea";
    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
    | NotifyFilters.FileName | NotifyFilters.DirectoryName;
    watcher.Filter = "*.*";
    watcher.Created += new FileSystemEventHandler(OnCreated);
    watcher.EnableRaisingEvents = true;
}
private void OnCreated()
{
    try
    {
        if (!myObjectToPrint.Dispatcher.CheckAccess())
        {
            myObjectToPrint.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
                new Action(
                   delegate()
                   {
                    //your code here...
                   }
                   )
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }          
}

Saludos..

Picrofo Software
  • 5,475
  • 3
  • 23
  • 37
  • Why on earth do you `try {} catch (Exception ex) { throw ex; }`? This does precisely nothing apart from ruin the stack trace making a crash harder to debug. – tomfanning Mar 24 '12 at 08:58
  • Also this doesn't seem to bear much relation to the problem the OP reported (unhandled exception in FileSystemWatcher after Renamed event fired) – tomfanning Mar 24 '12 at 09:01
  • This kind of seemingly pointless try...catch can be useful for debugging purposes. Placing a breakpoint on the "throw ex" will give you the ability to examine what's going on when you're trying to resolve some unexpected exception. It should be removed when you're done of course. – Jonas Rembratt Apr 10 '12 at 09:05