使用FileSystemWatcher监视目录


101

我正在使用Windows窗体应用程序监视目录,并将放置在其中的文件移动到另一个目录。

目前,它将文件复制到另一个目录,但是当添加另一个文件时,它将以没有错误消息结束。有时它确实会复制两个文件,然后再复制第三个文件。

这是因为我使用的是Windows Form Application而不是Console app?有什么办法可以阻止程序结束并继续监视目录?

private void watch()
{
  this.watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                         | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  watcher.Filter = "*.*";
  watcher.Changed += OnChanged;
  watcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
  //Copies file to another directory.
}

public void Dispose()
{
  // avoiding resource leak
  watcher.Changed -= OnChanged;
  this.watcher.Dispose();
}

Answers:


144

问题是通知过滤器。该程序试图打开一个仍在复制的文件。我删除了除LastWrite之外的所有通知过滤器。

private void watch()
{
  FileSystemWatcher watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastWrite;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

6
嗨,我使用的是这种方法,但是当我复制文件时,会引发两次事件:一次是将文件创建为空(复制开始),另一次是复制完成。如何避免此重复事件,任何过滤器都可以在没有自定义控件的情况下处理该事件?
dhalfageme,

@dhalfageme我检查这两个事件是否对文件夹中的应用程序有意义。
Eftekhari

30

您没有提供文件处理代码,但是我认为您在第一次编写这样的东西时犯了每个人都犯的相同错误:文件创建后将立即引发filewatcher事件。但是,完成文件需要一些时间。以文件大小为1 GB为例。该文件可能是由另一个程序创建的(Explorer.exe从某个地方复制该文件),但是要花几分钟才能完成该过程。该事件在创建时引发,您需要等待文件准备好被复制。

您可以通过循环使用功能来等待文件准备就绪。


25

原因可能是观察者被声明为方法的局部变量,并且在方法完成时被垃圾回收。您应该将其声明为班级成员。请尝试以下操作:

FileSystemWatcher watcher;

private void watch()
{
  watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                         | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
  //Copies file to another directory.
}

18
watcher变量保持活动状态(不收集垃圾),因为他订阅了Changed事件。
adospace'8

1
我相信这实际上是因为EnableRaisingEvents设置为true。我认为成员事件处理程序的状态与垃圾回收无关。我认为EnableRaisingEvents在这种情况下具有一种特殊的行为,我可能会称之为。
Matias Grioni '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.