// Делегат FileSystemEventHandler должен указывать на методы,
// имеющие следующую сигнатуру.
voidMyNotifacationiHandler( objectsource, FileSystemEventArgse)
Точно так же событие Renamed можно обработать с помощью типа делегата RenamedEventHandler, способного вызывать методы, соответствующие следующему шаблону.
// Делегат RenamedEventHandler должен указывать на методы,
// имеющие следующую сигнатуру .
voidMyNotificationHandler (objectsource , RenamedEventArgse)
Для иллюстрации процесса мониторинга файлов предположим, что мы создали на диске C новый каталог с именем MyFolder, cодержащий различные файлы *.txt (назовите их так, как пожелаете). Следующее консольное приложение осуществляет мониторинг файлов *.txt а каталоге MyFоlder и выводит сообщения о событиях, соответствующих созданию, удалению, изменению или переименованию файлов.
static void Main(string[] args) {
Console.WriteLine("***** Чудесный монитор файлов *****\n");
// Установка пути для каталога наблюдения.
FileSystemWatcher watcher = new FileSystemWatcher();
try {
watcher.Path = @"C:\MyFolder";
} catch(ArgumentException ex) {
Console.WriteLine(ex.Message);
return;
}
// Установка фильтров наблюдения.
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Наблюдение только за текстовыми файлами.
watcher.Filter = "*.txt";
// Добавление обработчиков событий.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
// Начало наблюдения за каталогом.
watcher.EnableRaisingEvents = true;
// Ожидание сигнала пользователя для выхода из программы.
Console.WriteLine(@"Нажмите 'q' для выхода из приложения.");
while(Console.Read() != 'q');
}
Следующие два обработчика событий просто выводят информацию о модификации текущего файла.
static void OnChanged(object source, FileSystemEventArgs e) {
// Уведомление об изменении, создании или удалении файла.
Console.WriteLine("Файл {0} {1}!", e.FullPath, e.ChangeType);
}
static void OnRenamed(object source, RenamedEventArgs e) {
// Уведомление о переименовании файла.
Console.WriteLine("Файл {0} переименован в\n{1}",
e.OldFullPath, e.FullPath);
}
Чтобы проверить работу этой программы, запустите приложение и откройте Проводник Windows. Попытайтесь переименовать, создать, удалить файлы *.txt в MyFolder или выполнить с ними какие-то другие действия, вы увидите, что консольное приложение реагирует на эти действия выводом различной информации о состоянии текстовых файлов (рис. 16.10).
Исходный код. Проект MyDirectoryWatcher размещен в подкаталоге, соответствующем главе 16.
Рис. 16.10. Наблюдение за текстовыми файлами
Асинхронный файловый ввод-вывод
В завершение нашего обзора пространства имен System.IO давайте выясним, как осуществляется асинхронное взаимодействие с типами FileStream. Один из вариантов поддержки асинхронного взаимодействия в .NET вы уже видели при рассмотрении многопоточных приложений (см. главу 14). Ввиду того, что ввод-вывод может занимать много времени, все типы, производные от System.IO.Stream, наследуют множество методов, разрешающих асинхронную обработку данных. Как и следует ожидать, эти методы работают в связке с типом IAsyncResult.
public abstract class System.IO.Stream: MarshalByRefObject, IDisposable {
…
public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state);
public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state);
public virtual int EndRead(IAsyncResult asyncResult); public virtual void EndWrite(IAsyncResult asyncResult);
}
Работа с асинхронными возможностями типов, производных от System. IO.Stream, аналогична работе с асинхронными делегатами и асинхронными удаленными вызовами методов. Маловероятно, что асинхронный подход может существенно улучшить доступ к файлам, но есть большая вероятность того, что от асинхронной обработки получат выгоду другие потоки (например, использующие сокеты). Так или иначе, следующий пример иллюстрирует подход, в рамках которого вы можете асинхронно взаимодействовать с типом FileStream.
class Program {
static void Main(string[] args) {
Console.WriteLine("Старт первичного потока, ThreadID = {0}", Thread.CurrentThread.GetHashCode());
Читать дальше