web-dev-qa-db-ja.com

FileSystemWatcherを使用してディレクトリを監視する

Windowsフォームアプリケーションを使用してディレクトリを監視し、そこにドロップされたファイルを別のディレクトリに移動しています。

現時点では、ファイルを別のディレクトリにコピーしますが、別のファイルが追加されると、エラーメッセージなしで終了します。 3つのファイルで終わる前に2つのファイルをコピーすることもあります。

これは、コンソールアプリではなくWindowsフォームアプリケーションを使用しているためですか?プログラムの終了を停止し、ディレクトリを監視し続ける方法はありますか?

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

問題は通知フィルターでした。プログラムは、まだコピー中のファイルを開こうとしました。 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

ファイル処理コードを提供しませんでしたが、最初にそのようなことを書いたときに誰もが犯したのと同じ間違いをしたと思います。ファイルが作成されるとすぐにfilewatcherイベントが発生します。ただし、ファイルの終了には時間がかかります。たとえば、ファイルサイズを1 GBとします。ファイルは別のプログラム(Explorer.exeがどこからコピーするか)によって作成される場合がありますが、そのプロセスを完了するには数分かかります。イベントは作成時に発生し、ファイルがコピーされる準備ができるまで待機する必要があります。

ループ内で this 関数を使用すると、ファイルの準備が整うまで待機できます。

24
nvoigt

理由は、ウォッチャーがメソッドのローカル変数として宣言されており、メソッドの終了時にガベージコレクションされるためです。クラスメンバとして宣言する必要があります。以下を試してください:

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