2016-08-11 8 views
0

私は、PCの利用可能なドライブ上のディレクトリ関連の変更を追跡し、その変更をsqlite DBに保存するアプリケーションを開発しています。下のコードのすべてが正常に正常に動作しています。しかし約100個のディレクトリとそのネストされたディレクトリを一緒にコピーしてテストしたところ、アプリケーションがフリーズされ、Windows OSのコピー処理がフリーズされました。FilewatcherはほとんどのPCリソースを消費しています

バルクファイルのコピー用のこのコードは、ほとんどのPCリソースを消費しているため、管理方法がわかりません。なぜ私はそれを最適化することができますか?代わりに "IncludeSubDirectories = False"を設定しますか?

class DirWatcher 
{   
    private FileSystemWatcher dirWatcher = null; 

    public void StartCapture() 
    { 
     string[] drives = Environment.GetLogicalDrives(); 

     foreach (string drive in drives) 
     { 
      DriveInfo driveInfo = new DriveInfo(drive); 
      if (driveInfo.DriveType == DriveType.Fixed) 
      { 
       //Director Watcher 
       dirWatcher = new FileSystemWatcher(drive); 
       dirWatcher.NotifyFilter = NotifyFilters.DirectoryName; 


       dirWatcher.Created += dirWatcher_Created; 
       dirWatcher.Deleted += dirWatcher_Created; 
       dirWatcher.Renamed += dirWatcher_Renamed; 

       dirWatcher.IncludeSubdirectories = true; 
       dirWatcher.EnableRaisingEvents = true; 

      } 
     } 
    } 

    void dirWatcher_Renamed(object sender, RenamedEventArgs e) 
    { 
     try 
     { 
      Task.Factory.StartNew(() => 
         { 
          saveToDB("Folder", 
            e.ChangeType.ToString(), 
            e.FullPath, 
            Utility.UnixDTstamp(DateTime.Now).ToString(), 
            Environment.UserName); 

         }); 
     } 
     finally 
     { 
      dirWatcher.Renamed -= dirWatcher_Renamed; 
     } 
    } 

    void dirWatcher_Created(object sender, FileSystemEventArgs e) 
    { 
     try 
     { 
      Task.Factory.StartNew(() => 
      { 
       saveToDB("Folder", 
         e.ChangeType.ToString(), 
         e.FullPath, 
         Utility.UnixDTstamp(DateTime.Now).ToString(), 
         Environment.UserName); 
      }); 
     } 
     finally 
     { 
      dirWatcher.Created -= dirWatcher_Created; 
     } 
    } 

    public void StopCapture() 
    { 
     dirWatcher.IncludeSubdirectories = false; 
     dirWatcher.EnableRaisingEvents = false; 
     dirWatcher.Dispose(); 
    } 

    public void saveToDB(string DirOrFile, string action, string path, string time, string userName) 
    { 
     //SavetoDB code will be here. 
    } 
} 
} 
+0

あなたのコードは多くのFSWオブジェクトを作成しますが、最後に作成されたものだけを停止します。あなたは決して他のインスタンスを保存しません。 'StartCapture'を呼び出すたびに、同じドライブを監視するより多くのインスタンスを作成します –

+0

別の問題は、各イベントに対して* new *タスクを開始することです。 10Kのイベントを受け取ったら、10Kのタスクを作成します。限られた並列度(デフォルトの1もOKです)でActionBlockを使用して、投稿したいものを受け入れてSQLiteに保存します。 DOP = 1の場合、SQLiteファイルへの同時書き込みアクセスを制御する必要はありません –

+0

1)make this Singleton Classを使用して、より多くのオブジェクトインスタンスを作成しないようにする必要があります。 2)私のアプリケーションでは、 'StartCapture'を一度だけ呼びます。私はあなたが言ったようにActionBlockを試しています。 – Jef

答えて

0

プログラムの速度を遅くしている(または倒すかもしれない)ものは、ネットワーク上のドライブに接続されています。私はあなたが正常にこれらのファイルウォッチャーを設定できるとは思わない、特にドライバがLinuxベースの場合。そして、たとえ可能であっても、それはパフォーマンスで氷河になるでしょう。

フォルダ階層を見ているときにFilewatcherがイベントを見逃しています。だから、一般的に、私はあなたが見つける必要があるか、この機能は、それが推奨されるべきではない欠陥の代替品を書く必要があると思います。おそらくあなたはWindowsのメッセージループを見ることができるフックですか?

関連する問題