1

FilesystemWatcher を使用して、monitor_directory に追加された PDF ファイルを監視する ac# プログラムを開発しています。ファイルがディレクトリに追加されるたびに、別のスレッドの無限 while ループで継続的にポップされる BlockingQueue にファイルを追加し、そこでファイル パスが追加されるのを待ちます。その後、ファイルの処理を続けます。 PDF ファイルの処理により、出力ディレクトリに移動されます。

ディスパッチスレッド:

    private static void ThreadProc(object param)
    {

        FileMonitorManager _this = (FileMonitorManager)param;
        FileProcessingManager processingManager = new FileProcessingManager();
        processingManager.RegisterProcessor(new ExcelFileProcessor());
        processingManager.RegisterProcessor(new PdfFileProcessor());

        while (true)
        {
            try
            {
                var path = (string)_this.FileQueue.Dequeue();
                if (path == null)
                    break;
                bool b = processingManager.Process(path);
                if (!b)
                {
                    _this.FileQueue.Enqueue(path);
                    Console.WriteLine("\n\nError on file: " + path);
                }
                else
                    Console.WriteLine("\n\nSucces on file: " + path);

            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

Process 関数は、ファイルが存在するかどうかをテストし、何らかの処理を行い、PDF ファイルを出力ディレクトリに移動します。

私は 2 つの問題に直面しました。つまり、処理の最後の部分は、そこにファイルを移動することです)、移動する場合は処理を続行し、移動しない場合は終了します。2. 何らかの理由でファイルのコンテンツへのアクセス中にエラーが発生した場合: ファイルは別のプロセスによって使用されています。Process 関数から FALSE を返し、ファイル パスをキューに再度追加します。

今..これは機能しますが、動作が少し遅くなります..私が直面している2つの問題を考慮して、これをマルチスレッドで行うにはどうすればよいですか.. 編集: イベントを取得したら、キューに追加します。ポップされ、キューが空になり、同じイベントが再び発生し、キューが空であるため追加され、基本的に同じイベントが2回処理されますか?

4

2 に答える 2

3

FileSystemWatcher はおしゃべりで有名です。

これは私がすることだと思います...

  1. On_Create 呼び出しからもう一度追加する前に、問題のファイルのエントリが BlockingQueue に既にあるかどうかを確認してください。
  2. Queue に多数の null パスがあると予想されますか? うまくいけば、null チェックは単なる予防策です。ただし、できる限り null パスをキューに入れないでください。
  3. ワーカースレッドでは、デキューして処理するだけです
  4. ワーカー スレッドで処理中にエラーが発生した場合は、再度キューに入れるか、例外的なケースとして取っておくことをお勧めします。これは、処理できないファイルが十分にあると、キューが占有されて速度が低下する可能性があるためです。

これをマルチスレッド化する簡単な方法は、パスをデキューするたびに新しいタスクを開始することです...

    Task.Factory.StartNew(() =>
        {
            try
            {
                var path = (string) _this.FileQueue.Dequeue();
                if (path == null)
                    break;
                bool b = processingManager.Process(path);
                if (!b)
                {
                    _this.FileQueue.Enqueue(path);
                    Console.WriteLine("\n\nError on file: " + path);
                }
                else
                    Console.WriteLine("\n\nSucces on file: " + path);

            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }
        });

運用コードの場合は、タスクにキャンセル トークンを渡し、ループとタスクを停止するメカニズムも必要です。

于 2013-06-19T16:03:26.550 に答える
1

1)ファイルは 2 つのステップで更新されるため、FileSystemWatcherは 2 回通知します。最初にdata、次にmetadataです。したがって、次のようなものを使用して、最新の書き込みがまだ考慮されていないことを確認できます。

File.GetLastWriteTime(file);

または、重複を確認できます。

2) マルチスレッドを使用していない: 一度に 1 つのファイルを処理するため、いくつかのスレッドを生成して Process メソッドを実行できます。たとえば、次を使用します。

ThreadPool.QueueUserWorkItem
于 2013-06-19T16:07:41.557 に答える