2012-02-06 2 views
9

У меня есть FileSystemWatcher, который отслеживает файл на сетевом ресурсе. Если произойдет событие, чтобы сделать доступ недоступным, возможно, из-за проблемы с сетью, FileSystemWatcher отключится.FileSystemWatcher Network Disconnect

Очевидно, что я могу обработать событие «Ошибка», возможно, некоторые записи и множество статей предлагают повторно подключить FSW внутри обработчика событий ошибки.

Но что, если сетевой ресурс по-прежнему недоступен внутри события ошибки. Затем мне нужно ввести таймер, чтобы проверить, доступен ли сетевой ресурс, и попытаться снова подключить FSW.

1) Есть ли лучший подход?

2) Есть ли свойство, которое позволяет мне определить, что FSW отключился от файла? Я замечаю, что есть непубличный член FSW «stopListening», который, как представляется, установлен в true, когда FSW отключается. Но это публично не подвергается

Любая помощь будет оценена ...

Благодаря Кевин

+0

возможно дубликат [FileSystemWatcher и сети отключиться?] (Http://stackoverflow.com/questions/281573/filesystemwatcher-and-network-disconnect) –

+0

Спасибо за ответ Эрно, но нет, это не не так. Я знаю, что я могу использовать событие Error для повторного подключения. Но когда возникает событие Error, что произойдет, если сетевой ресурс недоступен? Если у меня не будет какой-то попытки таймера/времени для повторного подключения, у меня нет другого события, чтобы попытаться снова подключиться! Кроме того, FSW не публикует публичное свойство, чтобы сообщить мне, что оно отключено. –

+0

Согласно сообщению, я предположил, что есть событие с ошибкой, которое вы можете использовать. И таймер - это хорошая идея для проверки доступности. –

ответ

1

Последующие меры в этом направлении. По предложению ресурса Microsoft на форумах MSDN я добавил это в Microsoft Connect.

Ключевые моменты от обратной связи от Microsoft: - событие ошибки не только для внутреннего переполнения буфера - Они добавят возможность разоблачения stopListening собственности в свой список предложений клиентов

Ссылка здесь: http://connect.microsoft.com/VisualStudio/feedback/details/727934/filesystemwatcher-error-handling

+0

Страница больше недоступна или нет разрешений для просмотра - делает ответ бесполезным :( – Darren

7

пару замечаний и предложений ... (которые росли и росли, как я печатал ... извините)

Событие FileSystemWatcher.Error запускается, когда FileSystemWatcher получает так много событий, которые происходят так быстро, что не могут обрабатывать их все. Он не отправляет при возникновении ошибки при просмотре файловой системы (например, при выходе из сети).

Я считаю, что у меня была аналогичная ситуация. Проблема в том, что когда сетевое соединение выпадает, FileSystemWatcher никогда не будет инициировано событие, потому что на самом деле он не может видеть, что он должен смотреть, но, похоже, он не знает об этом. Когда сетевое подключение возвращается, FileSystemWatcher не восстанавливается - т. Е. Он все еще не может видеть (восстановленное) соединение. Единственное решение, с которым мы столкнулись, казалось, надежно работает, - это таймер, который регулярно удаляет весь объект FileSystemWatcher и создает новый, устанавливая все события и папку для просмотра и т. Д. Так как отбрасывание и создание нового FileSystemWatcher (относительно) быстро (т.е. миллисекунды) вы можете настроить таймер на включение каждые 10 секунд или около того, не используя слишком большую часть процессора. Конечно, если сеть по-прежнему отсутствует, FileSystemWatcher не сможет видеть сеть независимо от того, что вы делаете. Но все в порядке, он повторит попытку через 10 секунд.

Две вещи, чтобы следить за этим решением:

  1. Когда таймер включается, то необходимо проверить, что FileSystemWatcher не в настоящее время обработки событий, и он должен ждать, если она есть. Таким образом, в событии таймера остановите таймер, остановите FileSystemWatcher для повышения событий, а затем дождитесь завершения любых событий FileSystemWatcher (использование lock (...) {...} - хороший способ сделать это).
  2. После удаления и воссоздания FileSystemWatcher вам необходимо вручную проверить любые события, которые могли произойти при обновлении FileSystemWatcher (или в то время, когда сеть была отключена). Например, если вы смотрите на создаваемые файлы и создается файл при обновлении FileSystemWatcher или при отключении сетевого подключения вы не получите события для этих файлов при запуске нового экземпляра FileSystemWatcher (например, поскольку файлы уже созданы).

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

+0

Спасибо за ответ Mark. После повторного чтения документа MSDN, я вижу, что вы правы, событие ошибки на самом деле не срабатывает, когда возникает ошибка при просмотре файловой системы, что было неправильным пониманием с моей стороны. –

+1

Ваш подход интересен, однако (вероятно, из-за дефекта дизайна), FileSystemWatcher на самом деле является статикой внутри службы WCF большого объема. Таким образом, концепция необходимости повторной инициализации через каждые 10 секунд, вероятно, не является для нас вариантом, даже небольшое поражение производительности может быть дорогостоящим для нашего требуемого времени отклика. Похоже, что ответа нет, так как мы не можем полностью полагаться на событие ошибки, оптимальным решением было бы переопределить наше решение для удаления FileSystemWatcher, поскольку оно выглядит ненадежным. –

0

Не было бы чем-то вроде этой работы? Кажется, работает для моего простого теста.

var fsw = new FileSystemWatcher("[folder]", "*.*") { IncludeSubdirectories = true}; 
var fsw_processing = false; 
fsw.Deleted += (s, e) => 
{ 
    fsw_processing = true; 
    fsw.EnableRaisingEvents = false; 
    //...... 
    fsw.EnableRaisingEvents = true; 
    fsw_processing = false; 
};  
fsw.Changed += (s, e) => 
{ 
    fsw_processing = true; 
    fsw.EnableRaisingEvents = false; 
    //...... 
    fsw.EnableRaisingEvents = true; 
    fsw_processing = false; 
};  
//governor thread to check FileSystemWatcher is still connected. 
//It seems to disconnects on network outages etc. 
Task.Run(() => 
{ 
    while (true) 
    { 
     if (fsw.EnableRaisingEvents == false && fsw_processing == false) 
     {       
      try 
      {fsw.EnableRaisingEvents = true;} 
      catch (Exception) { fsw.EnableRaisingEvents = false; }    
     } 
     System.Threading.Thread.Sleep(1000 * 10);//sleep 10 secs 
    } 
});