2017-09-04 148 views
2

我想要如此同步我的文件夾,所以我有10個Filesystemwatcher和4個Backgroundworkers。 想法是,一個觀察員可以打電話給4名工作人員,但我希望觀察員選擇一個主動和自由的工作人員,其他人不應該被觸發。c#filesystemwatcher和backgroundworker

經驗值:工人1被解僱,2-4沒有。

我在這裏做錯了什麼?

這裏是我的代碼

 private void watcher1_OnChanged(object source, FileSystemEventArgs e) 
     { 
      // File Name 
      string file = e.FullPath; 

      // refresh App.Config 
      ConfigurationManager.RefreshSection("appSettings"); 

      // Check Worker Active 
      bool worker1Active = Convert.ToBoolean(ConfigurationManager.AppSettings["worker1Active"]); 
      bool worker2Active = Convert.ToBoolean(ConfigurationManager.AppSettings["worker2Active"]); 
      bool worker3Active = Convert.ToBoolean(ConfigurationManager.AppSettings["worker3Active"]); 
      bool worker4Active = Convert.ToBoolean(ConfigurationManager.AppSettings["worker4Active"]); 

      // Watcher Nummer 
      string watcherNr = "Watcher 1"; 

      // Arguments to call worker 
      List<object> arguments = new List<object>(); 
      arguments.Add(file); 
      arguments.Add(watcher1_destinationPath); 
      arguments.Add(watcher1_sourcePath); 
      arguments.Add(watcherNr); 

      bool success = false; 

      while (!success == true) 
      { 
       try 
       { 
        using (Stream stream = new FileStream(file, FileMode.Open)) 
        { 

          if (worker1Active == true && worker1.IsBusy != true) 
          { 
           worker1.RunWorkerAsync(arguments); 
           success = true; 
           break; 
          } 

          if (worker2Active == true && worker2.IsBusy != true) 
          { 
           worker2.RunWorkerAsync(arguments); 
           success = true; 
           break; 
          } 

          if (worker3Active == true && worker3.IsBusy != true) 
          { 
           worker3.RunWorkerAsync(arguments); 
           success = true; 
           break; 
          } 

          if (worker4Active == true && worker4.IsBusy != true) 
          { 
           worker4.RunWorkerAsync(arguments); 
           success = true; 
           break; 
          } 
        } 
       } 
       catch 
       { 
        success = false; 
       } 
      } 
     } 
+0

你爲什麼不使用線程池掛鉤的創建,重命名,修改和刪除事件相同的事件處理程序(FileWatcher_Changed)? –

+1

阿曼說。這不是線程安全的。如果所有的工作人員都忙着工作堆積如何,你會怎麼做?您應該使用隊列排隊工作和線程池來完成工作。您讓文件系統監視器爲您排隊工作,並且可以將線程池​​設置爲許多工作人員在後臺執行工作。如果你想我可以做一個小例子的應用程序,並在這裏發佈代碼。 –

+0

線程的真正原因是您希望儘量減少事件回調中的工作量,否則您將面臨丟失文件系統更改的風險 – MickyD

回答

1

編輯螺紋:確保處理過程中鎖定文件,檢查處理之前的鎖。如果您有多個工作人員處理單個文件,則會遇到問題。只要確保在要處理的文件被鎖定時重新執行作業。它會自動重新排隊直到解鎖。當然,你需要重新解鎖它。

這是一個使用ThreadPool的示例應用程序: ThreadPool是線程安全的,意味着它在做它的工作時,它在不同的線程中執行它,這將保持您的UI響應並且不會阻塞。

玩得開心!

using System; 
using System.IO; 
using System.Threading; 

namespace FileWatcherThreadApp 
{ 
    class Program 
    { 

     static void Main(string[] args) 
     { 
      FileSystemWatcher fileWatcher = new FileSystemWatcher(@"C:\Users\BertSinnema\watch"); 

      //Enable events 
      fileWatcher.EnableRaisingEvents = true; 

      //Add event watcher 
      fileWatcher.Changed += FileWatcher_Changed; 
      fileWatcher.Created += FileWatcher_Changed; 
      fileWatcher.Deleted += FileWatcher_Changed; 
      fileWatcher.Renamed += FileWatcher_Changed; 

      var maxThreads = 4; 

      // Times to as most machines have double the logic processers as cores 
      ThreadPool.SetMaxThreads(maxThreads, maxThreads * 2); 


      Console.WriteLine("Listening"); 
      Console.ReadLine(); 

     } 

     //This event adds the work to the Thread queue 
     private static void FileWatcher_Changed(object sender, FileSystemEventArgs e) 
     { 
      ThreadPool.QueueUserWorkItem((o) => ProcessFile(e)); 
     } 

     //This method processes your file, you can do your sync here 
     private static void ProcessFile(FileSystemEventArgs e) 
     { 
      // Based on the eventtype you do your operation 
      switch (e.ChangeType) 
      { 
       case WatcherChangeTypes.Changed: 
        Console.WriteLine($"File is changed: {e.Name}"); 
        break; 
       case WatcherChangeTypes.Created: 
        Console.WriteLine($"File is created: {e.Name}"); 
        break; 
       case WatcherChangeTypes.Deleted: 
        Console.WriteLine($"File is deleted: {e.Name}"); 
        break; 
       case WatcherChangeTypes.Renamed: 
        Console.WriteLine($"File is renamed: {e.Name}"); 
        break; 
      } 
     } 
    } 


} 

如果你想瓦奇多個文件夾,您可以簡單地添加另一個FileSystemWatcher的和

+0

好的方法。謝謝1000次。 – Andre

+0

不客氣:) –

+0

@Andre,請標記答案,如果這是你在找什麼。它幫助我的計算器和stackoverflow。謝謝! –

0

您應該使用線程池。這會讓你的代碼看起來很乾淨,這就是你應該使用的線程機制。它會將任務放在其中一個空閒線程上,如果所有線程都忙,那麼它將等待其中一個線程空閒。

這裏是如何在c#中使用ThreadPool的鏈接。

https://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx https://www.dotnetperls.com/threadpool

此外,如果你想繼續在同一時間只有四個線程工作,你可以設置最大無。在線程 Here is how to do it.

+0

這意味着我有一個方法(worker)並且threadpool控制有多少線程並行工作。在這種情況下,隊列中有多少個作業? – Andre

+0

@Andre你可以有不同的工人方法。 可以有多個線程並行運行。如果您只想運行一個任務,請使用SerialWorkQueue。我有一個示例代碼。 將在單線程中運行所有內容,並等待一個工作線程完成,然後再繼續下一個工作線程。 –

+0

@Andre,檢查我的答案。您可以將多個FilesystemWatchers連接到事件處理程序,並簡單地對EventArgs類進行排隊。然後,在工作者運行的ProcessFile方法中,您可以調用任何其他基於changetype –