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


101

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

回答:


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
こんにちは、私はこのアプローチを使用していましたが、ファイルをコピーすると、イベントが2回発生します。この重複したイベントを回避する方法、それをカスタムコントロールせずに処理できるフィルター
dhalfageme

@dhalfagemeアプリケーションに意味のあるものがフォルダに表示されているかどうか、両方のイベントをチェックします。
エフテカリ

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変数は変更されたイベントにサブスクライブされているため、(ガベージコレクションではなく)存続します。
adospace

1
実際には、EnableRaisingEventsがに設定されてtrueいるためだと思います。メンバーのイベントハンドラーのステータスは、ガベージコレクションとは関係がないと思います。この場合、EnableRaisingEventsには、私が好むかもしれない特別な動作があると思います。
Matias Grioni、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.