ti-enxame.com

Usando o FileSystemWatcher para monitorar um diretório

Eu estou usando um aplicativo do Windows Forms para monitorar um diretório e mover os arquivos descartados para outro diretório.

No momento, ele copiará o arquivo para outro diretório, mas quando outro arquivo for adicionado, ele será encerrado sem nenhuma mensagem de erro. Às vezes copia dois arquivos antes de terminar no terceiro.

Isso é porque estou usando um aplicativo de formulário do Windows em vez de um aplicativo de console? Existe uma maneira de parar o programa e continuar assistindo o diretório?

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();
}
89
cheeseman

O problema foi os filtros de notificação. O programa tentava abrir um arquivo que ainda estava copiando. Eu removi todos os filtros de notificação, exceto 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;
}
128
cheeseman

Você não forneceu o código de manipulação de arquivos, mas presumo que você tenha cometido o mesmo erro que todos cometem ao escrever algo assim: o evento filewatcher será gerado assim que o arquivo for criado. No entanto, levará algum tempo para o arquivo ser concluído. Tome um tamanho de arquivo de 1 GB, por exemplo. O arquivo pode ser criado por outro programa (o Explorer.exe o copia de algum lugar), mas levará alguns minutos para concluir esse processo. O evento é gerado no momento da criação e você precisa aguardar o arquivo estar pronto para ser copiado.

Você pode esperar que um arquivo esteja pronto usando a função this em um loop.

24
nvoigt

O motivo pode ser que o inspetor seja declarado como variável local para um método e seja coletado quando o método é concluído. Você deve declará-lo como um membro da classe. Tente o seguinte:

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.
}
20
user1912419