FileSystemWatcher网络断开连接

我有一个FileSystemWatcher监视网络共享上的文件。 如果发生事件以使共享不可用,可能是由于网络问题,FileSystemWatcher将断开连接。

显然我可以处理“错误”事件,也许做一些日志记录,很多文章建议在错误事件处理程序中重新连接FSW。

但是,如果网络共享在错误事件中仍然不可用,该怎么办? 然后我需要引入一个计时器来测试网络共享是否可用并尝试重新连接FSW。

1)有更好的方法吗?

2)是否有一个属性允许我确定FSW已与文件断开连接? 我注意到FSW中有一个非公共成员“stopListening”,当FSW断开连接时,它似乎设置为true。 但这并未公开曝光

任何帮助,将不胜感激 …

谢谢凯文

一些评论和建议……(随着我的打字而变得越来越大……抱歉)

FileSystemWatcher.Error事件在FileSystemWatcher发生如此之多的事件以至于无法处理所有事件时触发了FileSystemWatcher.Error事件。 在观察文件系统时发生错误(例如网络丢失),它不会被触发。

我相信我有类似的情况。 问题是当网络连接断开时,FileSystemWatcher永远不会触发事件,因为它实际上看不到它应该看的内容,但似乎并没有意识到这一事实。 当网络连接恢复时,FileSystemWatcher无法恢复 – 即它仍然无法看到(恢复的)连接。 我们提出的唯一可靠的解决方案是使用定时器定期删除整个FileSystemWatcher对象并创建一个新的,设置所有事件和监视文件夹等。因为删除并创建一个新的FileSystemWatcher是(相对)快速(即毫秒)您可以将计时器设置为每10秒左右激活一次,而不会占用过多的处理器。 当然,如果网络仍处于运行状态,无论您做什么,FileSystemWatcher都无法看到网络。 但是没关系,它将在另外10秒再试一次。

使用此解决方案需要注意两件事:

  1. 当计时器激活时,它需要检查FileSystemWatcher当前是否正在处理任何事件,如果是,则需要等待。 所以在timer事件中,停止Timer,停止FileSystemWatcher引发事件,然后等待任何FileSystemWatcher事件完成(使用lock(…){…}这是一个很好的方法)。
  2. 删除并重新创建FileSystemWatcher后,您需要手动检查在刷新FileSystemWatcher时(或网络关闭时)可能发生的任何事件。 例如,如果您正在查看正在创建的文件,并且在刷新FileSystemWatcher时或在网络连接结束时创建了文件,则在启动FileSystemWatcher的新实例时,您将无法获取这些文件的事件(因为文件已经创建了)。

我希望有所帮助。

这是后续行动。 根据MSDN论坛上的Microsoft资源的建议,我将此添加到Microsoft Connect。

来自Microsoft反馈的要点: – 错误事件不仅仅是内部缓冲区溢出 – 它们还增加了将stopListening属性暴露给客户建议列表的可能性

链接到这里: http : //connect.microsoft.com/VisualStudio/feedback/details/727934/filesystemwatcher-error-handling

不会像这样的工作吗? 似乎适用于我的简单测试用例。

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 } });