2017-04-18 62 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

相關問題