| jakey |
|
|||
|
公告
日历
统计
导航 |
一.前言我们知道FileSystemWatcher 类用来侦听文件系统更改通知,并在目录或目录中的文件发生更改时引发事件。 在我们刚刚结束的项目当中也用到.NET的这个类。关于这个类的使用诸多帮助文档和搏友们都有过精彩的描述。 我们现在大概回顾一下这个类的基本特性:使用 FileSystemWatcher 监视指定目录中文件的创建,更改,删除,也可监视指定目录中的文件或子目录的创建,更改,删除等事件。可以创建一个组件来监视本地计算机、网络驱动器或远程计算机上的文件。可监视目录或文件中的若干种更改。例如,可监视文件或目录的 Attributes、LastWrite 日期和时间或 Size 方面的更改。通过将 NotifyFilter 属性设置为 NotifyFilters 值之一来达到此目的。有关可监视的更改类型的更多信息。 不过关于FileSystemWatcher类的错误处理部分,资料却显得相对少很多,MSDN上也几乎没有给出相关的介绍和例子。比如我们用FileSystemWatcher类来监控一个局域网或者远程机器的一个目录,在软件运行的情况下,网络突然出现问题,抑或,远程监控的目录被删除的情况下,即便此时网络恢复,或远程目录重建,FileSystemWatcher 也无法恢复正常工作状态。所以FileSystemWatcher类就应该有相应的处理,使得FileSystemWatcher对象从错误中恢复,对接下来发生的创建,更改,删除 等事件做出响应。 二.正文下面我们来看一下几段程序,在接下来的描述中来体会FileSystemWatcher错误处理的一个简单实例。希望能有用处。 在一般性的项目中,对于出现网络不通等错误时,需要进行重试,以便通过重试将系统从错误当中恢复。那么我们先来介绍一个用C#写的来进行局域网中的重试方法,这个方法将会在后面的方法中用到。 1
![]() /**//// <summary>2 /// Checks the Temporary folder connection when application start. If can't connect,3 /// this method will retry to connect, using the specified retry number and4 /// retry interval time in configuration file.5 /// </summary>6 /// <returns>Returns true if successfully connect to folder.7 /// Returns false if can't connect to folder after retrying.</returns>8 public bool CheckMonitorPath(string strMonitorPath, int nRetryInterval, int nMaxRetryCount)9 ![]() {10 // The temporary folder path existence flag11 bool bTemporaryPathExist = false;12 ![]() 13 if (!Directory.Exists(strMonitorPath))14 ![]() {15 if (nMaxRetryCount < 0)16 ![]() {17 // Retry to connect the Temporary folder18 CLogger.log.Info("MSG_INFO_STARTUP_CONNECT", strMonitorPath);19 int i = 0;20 for (; ; i++)21 ![]() { 22 if (RetryConnectFolder(i, nRetryInterval, strMonitorPath))23 ![]() {24 bTemporaryPathExist = true;25 break;26 }27 }28 }29 else30 ![]() {31 // Retry to connect the Temporary folder32 CLogger.log.Info("MSG_INFO_STARTUP_CONNECT", strMonitorPath);33 int i = 0;34 for (; i < nMaxRetryCount; i++)35 ![]() {36 if (RetryConnectFolder(i, nRetryInterval, strMonitorPath))37 ![]() {38 bTemporaryPathExist = true;39 break;40 }41 }42 if (nMaxRetryCount == i)43 ![]() {44 CLogger.log.Error("MSG_ERROR_RETRYCONNECTFAILED", strMonitorPath, i.ToString());45 bTemporaryPathExist = false;46 }47 }48 }49 else50 ![]() {51 bTemporaryPathExist = true;52 }53 return bTemporaryPathExist;54 }55 ![]() 56 ![]() /**//// <summary>57 /// Retry to connect the monitoring folder58 /// </summary>59 /// <param name="nCounter">The retry time</param>60 /// <param name="nRetryInterval">The retry interval time</param>61 /// <param name="strMonitorPath">The monitored path retry to connect</param>62 /// <returns>true: retry connect success, false: retry connect failed</returns> 63 private bool RetryConnectFolder(int nCounter, int nRetryInterval, string strMonitorPath)64 ![]() {65 if (0 != nCounter)66 ![]() {67 CLogger.log.Debug("MSG_DEBUG_STARTUP_CONNECT_RETRY", nCounter.ToString());68 }69 else70 ![]() {71 CLogger.log.Debug("MSG_DEBUG_STARTUP_CONNECT_RETRY", strMonitorPath);72 }73 try74 ![]() {75 if (Directory.Exists(strMonitorPath))76 ![]() {77 // If the Temporary folder connect successfully78 CLogger.log.Info("MSG_INFO_STARTUP_CONNECT_RETRYSUCCESS", strMonitorPath, nCounter.ToString());79 return true;80 }81 }82 catch (Exception ex)83 ![]() {84 CLogger.log.Error("MSG_ERROR_RETRYCONNECT_EXCEPTION", ex);85 return false;86 }87 // Retry to connect the temporary folder with certain interval time88 Thread.Sleep(nRetryInterval * 1000);89 return false;90 }91 ![]()
1
![]() /**//// <summary>2 /// The watcher method, to sense whether there is new file 3 /// is created in the network/local folder4 /// </summary>5 public void SystemWatch()6 ![]() {7 try8 ![]() {9 watcher.Path = RemoteMonitorPath;10 watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;11 // Sub-folder of the root can be monitored12 watcher.IncludeSubdirectories = true;13 watcher.Filter = "*.*";14 watcher.Created += new FileSystemEventHandler(OnChanged);15 // Add the event handlers: this event raised when it detects an error16 watcher.Error += new ErrorEventHandler(WatcherError);17 watcher.EnableRaisingEvents = true;18 ![]() 19 CLogger.log.Info("MSG_INFO_WATCHER_START");20 while (!bStop)21 ![]() {22 oEvent.WaitOne();23 }24 CLogger.log.Info("MSG_INFO_WATCHER_STOP");25 }26 catch (ArgumentException ex)27 ![]() {28 CLogger.log.Error("MSG_ERROR_WATCHER_RUNTIMEEXCEPTION", ex);29 }30 catch (FileNotFoundException ex)31 ![]() {32 CLogger.log.Error("MSG_ERROR_WATCHER_RUNTIMEEXCEPTION", ex);33 }34 catch (DirectoryNotFoundException ex)35 ![]() {36 CLogger.log.Error("MSG_ERROR_WATCHER_RUNTIMEEXCEPTION", ex);37 } 38 catch (Exception ex)39 ![]() {40 CLogger.log.Error("MSG_ERROR_WATCHER_RUNTIMEEXCEPTION", ex);41 }42 }43 ![]() 下面这个函数就是本文的重点,是FileSystemWatcher类的错误处理的函数,当发生监控路径错误时(网络问题,或者所监控文件夹被删除等),FileSystemWatcher类会自动捕捉错误,然后这个函数被调用,将FileSystemWatcher类从死亡中拯救出来。 1
![]() /**//// <summary>2 /// The error event handler3 /// </summary>4 /// <param name="source">The object instance</param>5 /// <param name="e">The ErrorEventArgs instance</param>6 private void WatcherError(object source, ErrorEventArgs e)7 ![]() {8 // Retry interval and max retry time (times)9 nRetryInterval = alertConfigValues.TempConnectInterval;10 nMaxRetryCount = alertConfigValues.TempMaxRetryCount;11 try12 ![]() {13 Exception watchException = e.GetException();14 CLogger.Log.Error("MSG_ERROR_FILESYSTEMWATCHER_ERROROCCURS", watchException.Message);15 ![]() 16 if (netSniffer.CheckMonitorPath(RemoteMonitorPath, nRetryInterval, nMaxRetryCount))17 ![]() {18 int nRetryCounter = 0; 19 // We need to create new version of the object because the20 // old one is now corrupted21 watcher = new FileSystemWatcher();22 while (!watcher.EnableRaisingEvents)23 ![]() {24 try25 ![]() {26 // This will throw an error at the27 // watcher.NotifyFilter line if it can't get the path.28 SystemWatch();29 Thread.Sleep(nRetryInterval * 1000);30 nRetryCounter++;31 ![]() 32 if (nMaxRetryCount == nRetryCounter)33 ![]() {34 break;35 }36 }37 catch38 ![]() {39 // Sleep for a while; otherwise, it takes a bit of40 // processor time41 Thread.Sleep(nRetryInterval * 1000);42 }43 } 44 // Stop the watcher45 CLogger.Log.Error("MSG_ERROR_FILESYSTEMWATCHER_RETRYFAILED ");46 }47 else48 ![]() { 49 // Stop the watcher50 CLogger.Log.Error("MSG_ERROR_FILESYSTEMWATCHER_RETRYFAILED ");51 }52 }53 catch (Exception ex)54 ![]() {55 CLogger.Log.Error("MSG_ERROR_FILESYSTEMWATCHER_ERROROCCURS", ex);56 }57 }58 ![]()
三.后记当初也是因为在做项目的时候遇到这个问题,即便恢复网络连接/重建文件夹FileSystemWatcher却无法再工作了,在百般苦恼与挣扎中才找到解决的办法,其实微软本来就提供的关于Error事件处理的使用办法,只不过没有明确讲明白其用法而已。 我写这篇短短小文的初衷,也仅仅是为了记录一下所谓心路历程,在工作的过程中,这个问题给我留下了很深的映像,同时也希望博友们如果遇到相似问题,这篇小文也许会有一些用处。程序员问答社区,解决您的IT难题
|
![]() |
|
| Copyright © jakey | Powered by: 博客园 模板提供:沪江博客 |