c#FileSystemWatcher - 每隔几秒钟就会产生数百个不需要的过多事件

时间:2017-04-18 05:05:42

标签: c# events filesystemwatcher

我正在使用FileSystemWatcher类,我需要它来监控我的插入式闪存驱动器,以便从任何地方监控任何创建或粘贴的文件。我每隔2秒刷新一次插入的驱动器列表(如果有任何新插入的驱动器),然后设置FileSystemWatcher.EnableRaisingEvents = true,然后在2秒后将其设置为“false”,然后再刷新插入的驱动器列表等。< / p>

当刷新间隔为2秒时,情况如下:

  1. 该程序工作1秒钟,我将文件粘贴到闪存驱动器 - FSW引发了一个“创建”事件。
  2. 该程序工作3秒钟,我将文件粘贴到闪存驱动器 - FSW引发了两个“创建”事件。
  3. 该程序工作5秒钟,我将文件粘贴到闪存驱动器 - FSW引发了三个“创建”事件。
  4. 该程序可以工作几分钟,然后我将文件粘贴到闪存驱动器上 - FSW引发了一大堆(大约)“创建”事件。
  5. BUT!刷新间隔为30秒时,情况如下:

    1. 该程序工作1秒钟,我将文件粘贴到闪存驱动器 - FSW引发了一个“创建”事件。
    2. 该程序工作3秒钟,我将文件粘贴到闪存驱动器 - FSW引发了一个“创建”事件。
    3. 该程序工作40秒,我将文件粘贴到闪存驱动器 - FSW引发了两个“创建”事件。
    4. 很明显,问题主要在于FileSystemWatcher没有正确清除,并且“not-happen-events”以某种方式累积在其中,然后当“Created”事件真正发生时它们一起出现

      必须保持刷新间隔低(约2-3-5秒)。我不能把它提高到几分钟。

      请帮忙。我坚持了六个小时。谢谢。对不起我的英语,它不是原生的。

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.IO;
      using System.Management;
      using System.Diagnostics;
      using System.Collections.Specialized;
      using System.Runtime.InteropServices;
      using System.Threading;
      
      private static FileSystemWatcher watcher1 = new FileSystemWatcher();
      
      private static DriveInfo[] GetDrivesList()
          {
              DriveInfo[] DriveList = DriveInfo.GetDrives();
              return DriveList;
          }
      
      static bool IsFileLocked(FileInfo file)
          {
              FileStream stream = null;
      
              if (is_directory == false)
              {
                  try
                  {
                      stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                  }
                  catch (IOException)
                  {
                      return true;
                  }
                  finally
                  {
                      if (stream != null)
                          stream.Close();
                  }
              }
      
              return false;
          }
      
          static void OnChanged(Object source, FileSystemEventArgs e)
          {
              FileInfo fileInfo = new FileInfo(e.FullPath);
              FileInfo fileInfo2 = new FileInfo(@"D:\Shadow Copies.log");
      
              if (Convert.ToString(e.ChangeType) == "Created")
              {
                  Console.WriteLine("File: {0} has been {1}", e.FullPath, e.ChangeType);
                  file_copied = false;
      
                  int length = Convert.ToString(e.FullPath).Length;
                  String Path = "";
                  String FileName = "";
                  for (int i = length - 1; i >= 0; i--)
                  {
                      if (Convert.ToString(e.FullPath)[i] != '\\')
                      {
                          Path += Convert.ToString(e.FullPath)[i];
                      }
                      else
                      {
                          break;
                      }
                  }
                  for (int i = Path.Length - 1; i >= 0; i--)
                  {
                      FileName += Path[i];
                  }
      
                  for (int i = FileName.Length - 1; i >= 0; i--)
                  {
                      if (FileName[i] == '.')
                      {
                          is_directory = false;
                          break;
                      }
                  }
      
                  string path = Convert.ToString(e.FullPath);
      
                  while (IsFileLocked(fileInfo) == true)
                  {
                      Thread.Sleep(100);
                      Console.WriteLine("Retrying in 1 sec...");
                  }
      
                  ProcessStartInfo psi = new ProcessStartInfo();
                  psi.CreateNoWindow = true;
                  psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                  psi.FileName = "cmd.exe";
                  psi.Arguments = @"/c xcopy " + path + @" D:\ShadowCopies\ /s /y";
                  Process proc = Process.Start(psi);
      
                  file_copied = true;
                  Console.WriteLine("File: {0} has been Copied", e.FullPath);
                  DateTime datetime = DateTime.Now;
      
                  CandidateLine = e.FullPath;
                  write_to_log = String.Format("{0} File: {1} has been Copied\r\n", datetime.ToString(), e.FullPath);
                  if (CandidateLine == LastLineWritten)
                      return;
                  while (IsFileLocked(fileInfo2) == true)
                  {
                      Thread.Sleep(100);
                      Console.WriteLine("Retrying...");
                  }
                  File.AppendAllText(@"D:\Shadow Copies.log", write_to_log);
                  LastLineWritten = CandidateLine;
      
                  is_directory = true;
      
                  ProcessStartInfo psi2 = new ProcessStartInfo();
                  psi2.CreateNoWindow = true;
                  psi2.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                  psi2.FileName = "cmd.exe";
                  psi2.Arguments = "/c for /d %F in (D:\\ShadowCopies\\*) do rd /s /q %F";
                  Process proc2 = Process.Start(psi2);
              }
          }
      
      private static void WatchersInitialize()
          {
              DriveInfo[] DriveList = GetDrivesList();
              string[] DriveListArray = new string[DriveList.Length - 1];
      
              for (int i = 0; i < DriveListArray.Length; i++)
              {
                  DriveListArray[i] = DriveList[i + 1].Name;
              } 
      
                  watcher1.IncludeSubdirectories = true;
                  watcher1.Path = DriveListArray[drive_position];
                  watcher1.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime |
                  NotifyFilters.DirectoryName | NotifyFilters.FileName |
                  NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
                  watcher1.Changed += new FileSystemEventHandler(OnChanged);
                  watcher1.Created += new FileSystemEventHandler(OnChanged);
                  watcher1.EnableRaisingEvents = true;
          return 0;
       }
      
      static void Main(string[] args)
          {
              while (true)
              {
                  watcher1.EnableRaisingEvents = false;
                  watcher2.EnableRaisingEvents = false;
                  watcher3.EnableRaisingEvents = false;
                  watcher4.EnableRaisingEvents = false;
                  watcher5.EnableRaisingEvents = false;
                  WatchersInitialize();
                  Thread.Sleep(2000);
              }
          }
      

2 个答案:

答案 0 :(得分:0)

你附上事件处理程序的地方我认为你应该首先将它们删除,以确保你没有将事件加倍。

watcher1.Changed -= new FileSystemEventHandler(OnChanged);
watcher1.Created -= new FileSystemEventHandler(OnChanged);
watcher1.Changed += new FileSystemEventHandler(OnChanged);
watcher1.Created += new FileSystemEventHandler(OnChanged);

答案 1 :(得分:0)

你应该初始化观察者一次并订阅一次事件处理程序,而不是在2秒睡眠的无限循环中初始化相同的观察者。在初始化块中,您将继续为已更改和已创建的事件添加偶数处理程序。因为这些是与观察者相同的物理实例,所以当你循环遍历无限循环时,你只是一个接一个地累积事件处理程序回调。

这很可能是因为您在每次迭代中越来越多地订阅同一事件时,您的事件会触发数百次。

您需要在while循环之外接听电话WatchersInitialize();