Search code examples
c#taskfilesystemwatcher

FileSystemWatcher can't get events from two directories when run as Release


If runs as Release occurs events only from 1st directory. No matter which is the first. In debug mode works properly.

public class Program
{
    private static void Main(string[] args)
    {
        string[] paths = File.ReadAllLines("config.txt");
        List<FolderWatch> lw = new List<FolderWatch>();
        foreach (string path in paths)
            if (Path.IsPathFullyQualified(path))
                lw.Add(new FolderWatch(path));
        Thread.Sleep(Timeout.InfiniteTimeSpan);
    }
}
public class FolderWatch
{
    private FileSystemWatcher watcher;
    public FolderWatch(string path)
    {
        watcher = new FileSystemWatcher();
        watcher.Path = path;
        watcher.Created += OnCreated;
        watcher.EnableRaisingEvents = true;            
    }
    private static void OnCreated(object source, FileSystemEventArgs e)
    {
            try
            {
                File.AppendAllText("log.txt", "Event occured");
            }
            catch { }
    }
}

Updated: I did some changes, regarding the scope of watcher.

string[] paths = File.ReadAllLines(configpath);

FileSystemWatcher[] w_arr = new FileSystemWatcher[paths.Length];

This works:

w_arr[0] = new FileSystemWatcher();
if (Path.IsPathFullyQualified(paths[0]))
    SetupWatcher(w_arr[0], paths[0]);

w_arr[1] = new FileSystemWatcher();
if (Path.IsPathFullyQualified(paths[1]))
    SetupWatcher(w_arr[1], paths[1]);

In a cycle it doesn't work. Only events from 1st directory occurs.

for (int i = 0; i < paths.Length; i++)
{
    if (Path.IsPathFullyQualified(paths[i]))
    {
        w_arr[i] = new FileSystemWatcher();
        SetupWatcher(w_arr[i], paths[i]);
    }
}

Finally thread sleeps and waits for events.

Thread.Sleep(Timeout.InfiniteTimeSpan);

private static void SetupWatcher(FileSystemWatcher watcher, string path)
{
    watcher.Path = path;
    watcher.EnableRaisingEvents = true;
    watcher.Filter = "*.pdf";
    watcher.Created += OnCreated;
    watcher.Error += OnError;
    GC.KeepAlive(watcher);
}

Solution

  • To make sure that the FileSystemWatchers will not get garbage collected before the end of the program, you could do this:

    public class FolderWatch
    {
        private FileSystemWatcher watcher;
    
        //...
    
        public void KeepAlive() => GC.KeepAlive(watcher);
    }
    

    ...and call the KeepAlive for all FolderWatchs at the end of the Main method:

    private static void Main(string[] args)
    {
        var lw = new List<FolderWatch>();
        //...
        Thread.Sleep(Timeout.InfiniteTimeSpan);
        lw.ForEach(w => w.KeepAlive());
    }