Проблема вызвана тем, что FSW сохраняет дескриптор открытого каталога , пока включены события . Исходный код показывает , что отключение событий также закрывает дескриптор. Чтобы удалить каталог, FSW должен быть отключен.
Вторая проблема, однако, заключается в том, что FileSystemWatcher watcher
определяется как переменная внутри конструктора Form1()
, что означает, что она является потерянной и сразу же доступна для сборки мусора еще до отображения формы. Однако сборщик мусора запускается не часто, а это значит, что нет гарантии, что он будет работать до нажатия Delete
. Поскольку наблюдатель нигде не хранится, его уже нельзя отключить.
По крайней мере, FSW необходимо сохранить в поле, а события перед удалением следует отключить. Мы также должны убедиться, что наблюдатель удаляется при удалении самой формы:
public class Form1
{
FileSystemWatcher _watcher;
public Form1()
{
...
_watcher=CreateDormantWatcher(path,pattern);
_watcher.EnableRaisingEvents=true ;
}
private void btnDelete_Click(object sender, EventArgs e)
{
_watcher.EnableRaisingEvents =false;
Directory.Delete("Alpha", true);//Recursively Delete
}
protected override void Dispose (bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_watcher.Dispose();
}
_watcher=watcher;
}
FileSystemWatcher CreateDormantWatcher(string path,string pattern)
{
//Don't store to the field until the FSW is
//already configured
var watcher=new FileSystemWatcher()
{
Path = path,
Filter = "pattern,
NotifyFilter = NotifyFilters.FileName
};
watcher.Changed += OnChanged;
watcher.Created += OnCreated;
watcher.Deleted += OnChanged;
watcher.Renamed += OnRenamed;
return watcher;
}
Простое исправление: добавьте его в качестве компонента
Возможно, лучшая идея,было бы добавить FileSystemWatcher на форму в качестве компонента. FileSystemWatcher наследуется от Component, что означает, что при помещении его в форму добавьте код создания и конфигурации в InitializeComponents()
. Он также будет утилизирован при утилизации всех других компонентов.
Если мы сделаем это, нам просто нужно будет переключить EnableRaisingEvents
, когда это необходимо.
Предполагая, что путь и шаблон заданы как свойства, а имя компонента - образное FileSystemWatcher1
это сводит код к:
public Form1()
{
InitializeComponent();
Directory.CreateDirectory(FileSystemWatcher1.Path);
FileSystemWatcher1.EnableRaisingEvents = true;
File.WriteAllText(alphaBeta + @"\Gamma.dat", "Delta");
}
private void btnDelete_Click(object sender, EventArgs e)
{
FileSystemWatcher1.EnableRaisingEvents = false;
Directory.Delete("Alpha", true);//Recursively Delete
}