Використання FileSystemWatcher для моніторингу каталогу


101

Я використовую програму Windows Forms для моніторингу каталогу та переміщення файлів, залишених у ньому, в інший каталог.

На даний момент він скопіює файл в інший каталог, але коли буде доданий інший файл, він просто закінчиться повідомленням про помилку. Іноді він копіює два файли, перш ніж закінчувати третій.

Це тому, що я використовую додаток для форми 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
Привіт, я використовував такий підхід, але коли я копіюю файл, подія піднімається двічі: один раз, коли файл створюється порожнім (копія починається) і ще один раз, коли копія закінчується. Як уникнути цієї дублюваної події, будь-який фільтр, здатний обробити його без спеціального контролю за цим?
dhalfageme

@dhalfageme Я перевіряю обидві події, чи є щось важливе для моєї програми у папці.
Ефтехарі

30

Ви не надали код обробки файлів, але я припускаю, що ви зробили ту саму помилку, яку роблять усі, коли вперше написали таку річ: подія filewatcher буде піднята, як тільки файл буде створений. Однак файл буде готовий деякий час. Візьмемо, наприклад, розмір файлу в 1 Гб. Файл може бути створений іншою програмою (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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.