Как заставить поток FileSystemWatcher работать вечно? - PullRequest
7 голосов
/ 19 марта 2009

Мне нужно запустить FileSystemWatcher в бесконечном цикле, чтобы отслеживать файл на предмет изменений, но этот файл будет изменяться только каждые несколько дней, а может быть, только один раз в неделю. В образце MSDN FileSystemWatcher есть цикл, пока пользователь не вводит q в консоли:

while(Console.Read()!='q');

Я не хочу, чтобы это было постоянно доступно, чтобы оно не было случайно убито - оно должно работать без вмешательства пользователя в бесконечном цикле. Должен ли я изменить цикл на

while (true);

чтобы поток не выходил? Само по себе это не идеально, так как будет привязывать ЦП - добавление вызова Thread.Sleep устранит нагрузку на ЦП, и в этом случае может быть длительный сон, поскольку файл очень редко изменяется. Это лучший путь? Как я должен убедиться, что этот поток остается живым, чтобы FileSystemWatcher мог действовать при изменении файла? Это выполняется на сервере Windows (с платформой .NET Framework версии 2.0), поэтому при необходимости можно было бы сделать его службой Windows.

Ответы [ 5 ]

9 голосов
/ 19 марта 2009

Если это работает на сервере, сервис выглядит как хорошая ставка.

Если вы хотите что-то более интерактивное, у меня в системном трее есть небольшое приложение, которое показывает мне, когда что-то происходит в нашей папке «Проблемы». Он использует метод Application.Run (), чтобы продолжать работу без необходимости зацикливания, т.е.

class MainEntryClass
{
    static void Main(string[] args)
    {
        FolderAlerter fa = new FolderAlerter(); 
        Application.Run();
    }
}

Затем я установил свой FileSystemWatcher в FolderAlerter.

2 голосов
/ 19 марта 2009

По сути, FileSystemWatcher использует некоторые из встроенных хуков для подписки на изменения и просто заставляет ОС вызывать ваших делегатов, когда происходит изменение. Поэтому все, что вам нужно сделать, это остановить выход из основного потока, он не должен ничего делать; К тому времени, как вы дойдете до этой строки, основная часть вашей программы закончилась, она сделала то, что ей нужно было сделать.

Простой способ сделать то, что вы хотите, - внести это изменение в образец из MSDN;

//while (Console.Read() != 'q') ;
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);

Это переведет ваш основной поток в спящий режим навсегда, но все равно позволит делегатам запускать и реагировать на изменения в каталоге. Обратите внимание, что он будет продолжать проходить через несколько изменений (так же, как образец MSDN).

Обратите внимание, что "while" в образце MSDN на самом деле мало что дает; Вы можете заменить эту строку просто на «Console.Read ()», которая затем заставит любой ключ выйти из приложения. Это всего лишь строка, которая запрещает выходу основного потока, чтобы он оставался активным при поступлении уведомлений о событиях.

Тем не менее, использование Sleep (Timeout.Infinite) оставляет ваше приложение в состоянии, когда оно не может быть легко остановлено пользователем, кроме как путем его закрытия. Если вы пишете это как консольное приложение, почему бы не придерживаться «нажмите Q, чтобы выйти»? Если вместо этого вы решите написать его как службу, вероятно, все будет в порядке, если вы обрабатываете события выключения / перезапуска и т. Д.

1 голос
/ 19 марта 2009

Чтобы сделать это, вы, вероятно, захотите создать ManualResetEvent в состоянии сброса и иметь основной поток WaitOne(). Для завершения какой-либо другой обратный вызов может просто Set() событие, которое приведет к возврату WaitOne().

0 голосов
/ 19 марта 2009

Sysinternals (теперь принадлежит Microsoft) имеет FileMon, который даст вам то, что вам нужно, с источником.

Цитирование с сайта

Сердце FileMon находится в виртуальном драйвер устройства, Filevxd.vxd. это динамически загружается, и в его инициализация устанавливает файл системный фильтр через сервис VxD, IFSMGR_InstallFileSystemApiHook, чтобы вставить себя в цепочку вызовов все запросы файловой системы.

Двоичные файлы и источники можно найти здесь: http://technet.microsoft.com/en-us/sysinternals/bb896642.aspx

0 голосов
/ 19 марта 2009

Вы можете использовать Thread.Sleep, чтобы избежать пустого цикла. Однако в случае, например, После перезагрузки системы служба Windows будет перезапущена автоматически. Другой подход, в зависимости от того, как устроена остальная часть программы / системы, заключается в использовании планировщика Windows для запуска логики опроса в отдельном файле .exe.

Если вы ищете надежное / отказоустойчивое решение, предпочтительнее использовать либо службу Windows, либо подход на основе планировщика Windows.

...