Menggunakan FileSystemWatcher untuk memantau direktori

101

Saya menggunakan Aplikasi Windows Forms untuk memantau direktori dan memindahkan file yang dijatuhkan di dalamnya ke direktori lain.

Saat ini itu akan menyalin file ke direktori lain, tetapi ketika file lain ditambahkan itu hanya akan berakhir tanpa pesan kesalahan. Terkadang itu menyalin dua file sebelum berakhir di yang ketiga.

Apakah ini karena saya menggunakan Aplikasi Formulir Windows daripada aplikasi konsol? Adakah cara agar saya dapat menghentikan program agar tidak berakhir dan tetap mengawasi direktori?

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

Jawaban:

144

Masalahnya adalah filter beri tahu. Program mencoba membuka file yang masih disalin. Saya menghapus semua filter pemberitahuan kecuali untuk 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;
}
tukang keju
sumber
6
Hai, Saya menggunakan pendekatan ini tetapi ketika saya menyalin file, acara dimunculkan dua kali: satu kali ketika file dibuat kosong (penyalinan dimulai) dan sekali lagi saat penyalinan selesai. Bagaimana cara menghindari peristiwa duplikat ini, filter apa pun yang dapat menanganinya tanpa kontrol khusus untuk itu?
dhalfageme
@dhalfageme Saya memeriksa kedua peristiwa tersebut jika sesuatu yang berarti untuk aplikasi saya muncul di folder.
Eftekhari
30

Anda tidak memberikan kode penanganan file, tetapi saya berasumsi bahwa Anda melakukan kesalahan yang sama yang dilakukan semua orang saat pertama kali menulis hal seperti itu: acara filewatcher akan dimunculkan segera setelah file dibuat. Namun, perlu waktu beberapa saat untuk menyelesaikan file. Ambil ukuran file 1 GB misalnya. File mungkin dibuat oleh program lain (Explorer.exe menyalinnya dari suatu tempat) tetapi akan membutuhkan beberapa menit untuk menyelesaikan proses itu. Acara dimunculkan pada waktu pembuatan dan Anda harus menunggu file siap untuk disalin.

Anda dapat menunggu file siap dengan menggunakan fungsi ini dalam satu putaran.

nvoigt
sumber
25

Alasannya mungkin karena pengawas dideklarasikan sebagai variabel lokal ke suatu metode dan itu adalah sampah yang dikumpulkan saat metode selesai. Anda harus mendeklarasikannya sebagai anggota kelas. Coba yang berikut ini:

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.
}
pengguna1912419
sumber
18
watchervariabel tetap hidup (bukan sampah yang dikumpulkan) karena dia berlangganan acara Berubah.
adospace
1
Saya percaya ini sebenarnya karena EnableRaisingEvents diatur ke true. Saya tidak berpikir status penangan acara anggota ada hubungannya dengan pengumpulan sampah. Saya pikir EnableRaisingEvents memiliki, apa yang mungkin saya sebut lebih baik, perilaku khusus dalam kasus ini.
Matias Grioni