【问题标题】:FileSystemWatcher stops catching eventsFileSystemWatcher 停止捕获事件
【发布时间】:2011-05-31 07:09:33
【问题描述】:

我正在编写一个 c# 程序,以便在添加或删除文件时通知我。我在我的 Windows 7 机器上运行它并观察我们网络上的 FTP 服务器。

它工作正常,但会突然停止捕捉任何事件。我猜它可能会失去与服务器的连接或网络出现故障。

如何在代码中处理这种情况。是否有一些异常我可以观察并尝试重新启动 FileSystemWatcher 对象。

任何建议和代码示例将不胜感激。

【问题讨论】:

  • 那么如果已经上传了1kb的文件,怎么知道传输完成了呢?我认为您需要在这里重新考虑您的方法。
  • 查看这个关于使用 FileSystemWatcher stackoverflow.com/questions/699538/… 读取创建的文件时出现异常的问题
  • 它可以很好地捕捉创建或删除文件的时间。我只需要知道如何从丢失的连接或网络故障中恢复。 FileSystemWatcher 对象是否抛出任何类型的异常?
  • 我想我知道我现在需要做什么了。捕获 fileSystemWatcher 抛出的异常,然后在再次访问服务器时尝试在其上重新启用引发事件。我不明白我会把 try/catch 放在哪里。

标签: c# filesystemwatcher


【解决方案1】:

我需要为 FileSystemWatcher 添加一个错误处理程序

fileSystemWatcher.Error += new ErrorEventHandler(OnError);

然后添加这段代码:

private void OnError(object source, ErrorEventArgs e)
{
    if (e.GetException().GetType() == typeof(InternalBufferOverflowException))
    {
        txtResults.Text += "Error: File System Watcher internal buffer overflow at " + DateTime.Now + "\r\n";
    }
    else
    {
        txtResults.Text += "Error: Watched directory not accessible at " + DateTime.Now + "\r\n";
    }
    NotAccessibleError(fileSystemWatcher ,e);
}

这是我如何重置 SystemFileWatcher 对象:

   static void NotAccessibleError(FileSystemWatcher source, ErrorEventArgs e)
    {
        source.EnableRaisingEvents = false;
        int iMaxAttempts = 120;
        int iTimeOut = 30000;
        int i = 0;
        while (source.EnableRaisingEvents == false && i < iMaxAttempts)
        {
            i += 1;
            try
            {
                source.EnableRaisingEvents = true;
            }
            catch
            {
                source.EnableRaisingEvents = false;
                System.Threading.Thread.Sleep(iTimeOut);
            }
        }

    }

我认为这段代码应该做我想做的事。

【讨论】:

  • 如果这确实解决了问题,您应该将其标记为答案。对于它的价值,抛出的异常是什么?
  • 克里斯,其实我并不关心异常是什么,我只是想确保 FileSystemWatcher 对象重新启动。
【解决方案2】:

之前的答案并没有完全解决它,我不得不重置观察者,而不仅仅是打开和关闭它。 我在 window 服务

上使用 filesystemwatcher
void NotAccessibleError(FileSystemWatcher source, ErrorEventArgs e)
{
    int iMaxAttempts = 120;
    int iTimeOut = 30000;
    int i = 0;
    while ((!Directory.Exists(source.Path) || source.EnableRaisingEvents == false) && i < iMaxAttempts)
    {
        i += 1;
        try
        {
            source.EnableRaisingEvents = false;
            if (!Directory.Exists(source.Path))
            {
                MyEventLog.WriteEntry("Directory Inaccessible " + source.Path + " at " + DateTime.Now.ToString("HH:mm:ss"));
                System.Threading.Thread.Sleep(iTimeOut);
            }
            else
            { 
                // ReInitialize the Component
                source.Dispose();
                source = null;
                source = new System.IO.FileSystemWatcher();
                ((System.ComponentModel.ISupportInitialize)(source)).BeginInit();
                source.EnableRaisingEvents = true;
                source.Filter = "*.tif";
                source.Path = @"\\server\dir";
                source.NotifyFilter = System.IO.NotifyFilters.FileName;
                source.Created += new System.IO.FileSystemEventHandler(fswCatchImages_Changed);
                source.Renamed += new System.IO.RenamedEventHandler(fswCatchImages_Renamed);
                source.Error += new ErrorEventHandler(OnError);
                ((System.ComponentModel.ISupportInitialize)(source)).EndInit();
                MyEventLog.WriteEntry("Try to Restart RaisingEvents Watcher at " + DateTime.Now.ToString("HH:mm:ss"));
            }
        }
        catch (Exception error)
        {
            MyEventLog.WriteEntry("Error trying Restart Service " + error.StackTrace + " at " + DateTime.Now.ToString("HH:mm:ss"));
            source.EnableRaisingEvents = false;
            System.Threading.Thread.Sleep(iTimeOut);
        }
    }
}

【讨论】:

  • 这似乎会继续循环并重新创建文件系统观察程序,即使它在某个时候成功。 “成功”循环不应该中断吗?
  • @Matt 它应该在 1) 路径存在(可访问)和 b)EnableRaisingEvents == true 上中断。
  • 这会将一个新的FileSystemWatcher 分配给一个局部变量。调用者仍然拥有对旧实例的引用,该实例现已被释放。
【解决方案3】:

您可以创建一个启动 FileSystemWatcher 的方法,如果出现错误,只需重新启动它。

    private void WatchFile()
    {
        try
        {
            fsw = new FileSystemWatcher(path, filter)
            {
                EnableRaisingEvents = true
            };                
            fsw.Changed += Fsw_Changed;                
            fsw.Error += Fsw_Error;
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    private void Fsw_Error(object sender, ErrorEventArgs e)
    {
        Thread.Sleep(1000);
        fsw.Changed -= Fsw_Changed;
        fsw.Error -= Fsw_Error;
        WatchFile();
    }

【讨论】:

  • 每次系统引发错误时,您都会创建一个新的 FileSystemWatcher。我认为您将遇到堆栈溢出异常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多