2017-04-18 64 views
0

我正在使用FileSystemWatcher类,我需要它来监视插入的闪存驱动器是否可以从任何地方创建或粘贴文件。我每2秒刷新一次插入驱动器列表(如果有任何新插入的到达驱动器),然后设置FileSystemWatcher.EnableRaisingEvents = true,然后在2秒后将其设置为“false”,然后再次刷新插入的驱动器列表等。c#FileSystemWatcher - 每隔几秒钟提高数百个不需要的过多事件

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

  1. 该方案适用于1秒,我粘贴文件到闪存驱动器 - FSW提出了ONE“创建”事件。
  2. 该程序工作3秒,我将该文件粘贴到闪存驱动器 - FSW引发两个“创建”事件。
  3. 该程序工作5秒,我将该文件粘贴到闪存驱动器 - FSW提出了三个“创建”事件。
  4. 该程序工作几分钟,我将该文件粘贴到闪存驱动器--FSW引发了一个(大约)“创建”事件。

但是!当刷新间隔为30秒时,情况如下:

  1. 该程序工作1秒,我将该文件粘贴到闪存驱动器--FSW引发一个“创建”事件。
  2. 该程序工作3秒,我将该文件粘贴到闪存驱动器 - FSW引发一个“创建”事件。
  3. 该程序工作40秒,我将该文件粘贴到闪存驱动器 - FSW引发两个“创建”事件。

很明显,问题的事实主机,该FileSystemWatcher的没有正确清除本身和“不发生的事件”被莫名其妙地在它积累,那么他们出现一起“创建”时事件真的发生。

有必要保持刷新间隔低(约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); 
     } 
    } 
+0

watcher2,watcher3,...他们是什么?考虑创建一个[最小,完整和可验证的示例](https://stackoverflow.com/help/mcve) – Lanorkin

回答

0

如果您附加了事件处理程序,我认为您应该先删除它们,以确保您没有将事件加倍。

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

谢谢,来自未知国家的未知家伙。你是一个真正的生命保护者。它像一个魅力。我从来没有猜到这个EventHandler的。从俄罗斯致敬! – renat2

0

你应该进行一次初始化守望订阅事件处理一次,而不是你有相同的观察者的初始化与2秒睡眠无限循环。在您的初始化块中,您不断添加更改和创建事件的偶处理程序。由于这些是观察者的相同物理实例,因此当循环访问无限循环时,您只会逐个积累事件处理函数回调。

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

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

+0

无论如何,我尝试了上面评论中描述的方式,它工作。不需要尝试你的一个:) – renat2

相关问题