如何在执行程序时无限期启动c# FileSystemWatcher函数?

How to start the c# FileSystemWatcher function indefinitely when executing the program?

我正在使用 .Net Framework 开发 windows 程序。

我想创建一个程序,当使用 FileSystemWatcher 在特定文件夹中创建文件时执行函数。

下面是我的代码。

public async Task<int> CollectFunc() {
   string path = @"C:\test";
   try
   {
      FileSystemWatcher watcher = new FileSystemWatcher
      {
      Path=path
      Filter="test.log"
      };
      watcher.Created += new FileSystemEventHandler(WatcherFunc);
      watcher.IncludeSubdrectories=true;
      watcher.EnableRaisingEvents=true;
   }
   catch
   {
      Console.WriteLine("Error");
   }
   

   while(true)
   {
      await Task.Delay(100000);
   }
}

public async void WatcherFunc(object source, FileSystemEventArgs e) {
   Console.WriteLine("File Created: " + e.FullPath);
}

当我启动程序时,文件创建会受到监控,直到我关闭程序。

示例如下。

9 月 1 日,创建了以下文件。 C:\test200901\test.log 然后程序打印“文件已创建:C:\test200901\test.log”。

9 月 2 日 C:\test200902\test.log文件创建, 然后程序将输出“文件已创建:C:\test200902\test.log”。

...

但有时 Watcher 不工作,我必须重新启动程序。

如果有比我的源代码更好或更稳定的逻辑,请告诉我。

期待您的回复。

试试这些改变:

// Introduce a class field, to prevent the watcher reference from going out of scope.
private FileSystemWatcher watcher = null;

public void CollectFunc() { // no need for async any more ...
   string path = @"C:\test";
   try
   {
      // Init class field
      watcher = new FileSystemWatcher
      {
      Path=path
      Filter="test.log"
      };
      watcher.Created += new FileSystemEventHandler(WatcherFunc);
      watcher.IncludeSubdrectories=true;
      watcher.EnableRaisingEvents=true;
   }
   catch (Exception ex)
   {
      // Better know what the problem actually was.
      Console.WriteLine($"Error: {ex.Message}");
   }
   
   // It's a winforms app - we don't need to block this => away with while(true)
}

public async void WatcherFunc(object source, FileSystemEventArgs e) 
{
   // Just in case, catch and log exceptions
   try{
       Console.WriteLine("File Created: " + e.FullPath);
   } catch( Exception ex ) {
      // TODO: Log Exception or handle it.
   }
}

最重要的是:这是一个已知问题,大量和频繁的更改会导致观察程序中的某些缓冲区溢出(如果仍然适用,但我记得 运行 到此几年前)。

此处提到缓冲区溢出问题https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.internalbuffersize?view=netcore-3.1#remarks

注册一个处理程序到 Error 事件可能也是值得的:https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.error?view=netcore-3.1

我猜你在事件处理程序中的 Console.WriteLine 只是一个示例代码,你实际上做的不止于此。过去,我发现如果我在这里保持代码非常小并尽快处理事件,它可以减轻 FileSystemWatcher 缓冲区的压力。

所以,我所做的是将文件路径放入队列中,并让该队列在不同的线程上处理。这可确保尽快处理事件,同时不会丢失任何事件。 Peeks 可以被越来越大的队列捕获,并由另一个线程独立处理。换句话说:事情堆积 观察者缓冲区之外。