FileSystemWatcher вызывает сбои на рабочем столе

Я пишу решение, где я использую некоторые файлы конфигурации, которые должны быть доступны для редактирования во время выполнения. Я использовал FileSystemWatcher для этой цели раньше и никогда не имел много проблем с этим, но теперь он вызывает CTD в событии "rename".

Этот (бесполезный) фрагмент кода воссоздает проблему в моей настройке:

private static int _s_renamed;
private static int _s_created;
private static int _s_errors;

private static void monitorConfiguration(string configRootFolder)
{
    var fsw = new FileSystemWatcher(configRootFolder, ConfigFilePattern)
    {
        NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName,
        IncludeSubdirectories = false
    };
    fsw.Renamed += (sender, args) => ++_s_renamed; // <-- ! CTD efter this one !
    fsw.Created += (sender, args) => ++_s_created;
    fsw.Error += (sender, args) => ++_s_errors; 
    fsw.EnableRaisingEvents = true;
}

Сбой происходит от FileSystemWatcher. Если я устанавливаю точку останова в обработчике события для FileSystemWatcher.Renamed, он попадает, но приложение падает, когда я выхожу из него. Если я установил точку останова в обработчике события FileSystemWatcher.Created, этого не произойдет.

Любые предложения?


ИЗМЕНИТЬ 1: Я запускаю .NET 4 на платформе Windows 7 x64 (Ultimate) Я видел несколько обсуждений по этим типам проблем, но все они были связаны с людьми, пытающимися обновить материал пользовательского интерфейса (который должен выполняться из основного/пользовательского потока) из обработчиков событий. Поэтому я просто пытаюсь увеличить количество счетчиков в экспериментальном коде.

Ответ 1

Просто уточнить:

Проблема здесь заключалась в том, что у меня было больше/более старых потребителей FileSystemWatcher в другом месте моей системы, и одна из них вызвала необработанное исключение. Проблема заключается в том, что исключение попадает в совершенно другой поток и заставляет приложение работать на рабочем столе. Время заманило меня в мысли, что это мой новый потребитель, который каким-то образом вызывают Isse, но когда я следовал совету Криса Шаина (см. Комментарии в вопросе ввода), чтобы включить break on exceptions (msdn.microsoft.com/en-us/library/d14azbfh.aspx) Я сразу нашел настоящего виновника.

Я предпочел бы кредитовать Криса решением, но он никогда не переводил его так, как он есть. Надеюсь, мы кое-что узнали.

Спасибо всем и счастливое кодирование

/Jonas

Ответ 2

Вы можете столкнуться с любой из этих трех ситуаций.

  • Прошедший каталог не существует, а файл io не найден.
  • Указанный каталог действителен, но процесс, выполняющий его, не имеет прав доступа
  • Аргументы (отправитель, args), которые были переданы, могут быть нулевыми и ваш код (так как это пример, и мы не можем видеть реальный код) не обрабатывает значение null и бросает ошибку.

Ответ 3

В .NET вы должны синхронизировать поток, сгенерированный FileSystemWatcher, с помощью потока пользовательского интерфейса. Для этого элементы управления пользовательского интерфейса имеют такой метод, как: myControl.Invoke(...) для этого эффекта. Любой другой способ попытаться синхронизироваться будет иметь некоторые случайные эффекты, такие как сбои, исключения и т.д.

см. здесь: http://msdn.microsoft.com/en-us/magazine/cc300429.aspx http://weblogs.asp.net/justin_rogers/pages/126345.aspx

надеюсь, что это поможет

Ответ 4

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

private void InitWatch()
{
    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = @"C:\LoQueSea";
    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
    | NotifyFilters.FileName | NotifyFilters.DirectoryName;
    watcher.Filter = "*.*";
    watcher.Created += new FileSystemEventHandler(OnCreated);
    watcher.EnableRaisingEvents = true;
}
private void OnCreated()
{
    try
    {
        if (!myObjectToPrint.Dispatcher.CheckAccess())
        {
            myObjectToPrint.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
                new Action(
                   delegate()
                   {
                    //your code here...
                   }
                   )
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }          
}

Saludos..