Вопрос по copy, io, filesystemwatcher, winforms, c# – Использование FileSystemWatcher для мониторинга каталога

83

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

В данный момент он скопирует файл в другой каталог, но при добавлении другого файла он просто завершится без сообщения об ошибке. Иногда он копирует два файла, а потом заканчивает третий.

Это потому, что я использую приложение Windows Form, а не консольное приложение? Есть ли способ, как остановить программу и продолжить просмотр каталога?

private void watch()
{
  FileSystemWatcher 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.
}
Просто для записи - приведенный выше код имеет утечку ресурсов. astrowalker
@astrowalker круто с твоей стороны это заметить. Если вы нене возражаете, как насчет редактирования кода операции? user23333

Ваш Ответ

3   ответа
123

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

что наблюдатель объявляется как локальная переменная для метода, и он собирается после завершения метода. Вы должны объявить это как член класса. Попробуйте следующее:

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.
}
Я считаю, что это на самом деле, потому что EnableRaisingEvents установлен вtrue, Я не думаю, что статус обработчиков событий-членов связан с сборкой мусора. Я думаю, что EnableRaisingEvents имеет, что я бы с радостью назвал, особым поведением в этом случае. Matias Grioni
watcher Переменная остается в живых (не сборщик мусора), потому что он подписан на событие Changed. adospace
22

но я предполагаю, что вы сделали ту же ошибку, которую все делают, когда впервые пишут такую вещь: событие filewatcher будет вызвано, как только файл будет создан. Однако для завершения файла потребуется некоторое время. Возьмите, например, размер файла 1 ГБ. Файл может быть создан другой программой (Explorer.exe копирует его откуда-то), но для завершения этого процесса потребуется несколько минут. Событие возникает во время создания, и вам нужно дождаться готовности файла для копирования.

Вы можете подождать, пока файл будет готов, используяэтот функция в цикле.

Похожие вопросы