Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileSystemWatcher - event not firing the second time

I have an application that launches other applications, and then waits for them to create a specific data file (it watches one application at a time). Each time an application is launch it watches a specific directory for a specific file to be created. I am using the FileSystemWatcher to do this (set it to the directory, then filter for the correct file name). This works great the first time (always), but the second application launched never fires the event. The only way it seems to fire the event is if I place a break-point in the event handler, or if I have a Thread.Sleep command in the event handler. This seems very strange to me...is there some race condition that I'm not aware of? Here is the code. Notice I have a Thread.Sleep(500). With this line the code works every time. Without it will fail. I'm really not comfortable relying on a Sleep command. I'm not sure what condition will cause that not to work as well.

    public static void watchFiles(string path)
    {
        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = path;
        watcher.Created += new FileSystemEventHandler(watcher_Handler);
        watcher.EnableRaisingEvents = true;
   }

    public static void watcher_Handler(object sender, FileSystemEventArgs e)
    {
        //Hack - the sleep allows the second and third application to be caught by this event
        Thread.Sleep(500);

        switch (e.ChangeType.ToString())
        {
            case "Changed":
                break;
            case "Deleted":
                break;
            case "Created":
                if (e.Name == "log.dat")
                {
                    parseDataFile();
                    moveHTMLtoLMS();

                }
                break;
            default:
                break;
        }
    }

Anyone know why I need to have that Sleep (or break-point) to get the code to work a second time?

like image 350
cwo Avatar asked Dec 27 '10 20:12

cwo


1 Answers

According to the documentation of the System.IO.FileSystemWatcher class:

The Windows operating system notifies your component of file changes in a buffer created by the FileSystemWatcher. If there are many changes in a short time, the buffer can overflow. This causes the component to lose track of changes in the directory, and it will only provide blanket notification. Increasing the size of the buffer with the InternalBufferSize property is expensive, as it comes from non-paged memory that cannot be swapped out to disk, so keep the buffer as small yet large enough to not miss any file change events. To avoid a buffer overflow, use the NotifyFilter and IncludeSubdirectories properties so you can filter out unwanted change notifications.

It might be that the event isn't being consumed fast enough and the internal buffer isn't large enough to handle all the notifications. By default, the watcher handles FileName, DirectoryName, LastWrite notifications yet you only consume creation events (both file and directory). Are your applications running in quick succession? I'd try putting a delay between the invocations of your applications (instead of the event handler), use more specific filters (just the FileName notification or watch only for log files using the Filter property), increase the internal buffer size or any combination of the above. I think that should fix your problem.

like image 67
Jeff Mercado Avatar answered Oct 04 '22 11:10

Jeff Mercado