首页 > 解决方案 > FileSystemWatcher 在作为 Release 运行时无法从两个目录获取事件

问题描述

如果以 Release 方式运行,则仅从第一个目录发生事件。不管哪个是第一。在调试模式下工作正常。

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 { }
    }
}

更新:关于watcher.

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

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

这有效:

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]);

在一个循环中它不起作用。仅发生来自第一个目录的事件。

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

最后线程休眠并等待事件。

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);
}

标签: c#taskfilesystemwatcher

解决方案


为了确保FileSystemWatchers 在程序结束之前不会被垃圾收集,你可以这样做:

public class FolderWatch
{
    private FileSystemWatcher watcher;

    //...

    public void KeepAlive() => GC.KeepAlive(watcher);
}

...并在方法末尾调用KeepAlivefor all :FolderWatchMain

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

推荐阅读