2011-07-12 11 views
6

私のサーバー上のディレクトリにあるファイルを処理するのに効果的なアプリがあります。このプロセスは次のとおりです。ファイルが同時に到着したときに処理する#

1) check for files in a directory 
2) queue a user work item to handle each file in the background 
3) wait until all workers have completed 
4) goto 1 

これはうまく動作し、私は二回処理されているか、複数のスレッドが同じファイルのために生み出されたされている同じファイルを心配することはありません。ただし、処理に時間がかかりすぎるファイルが1つある場合は、その1つのファイルでステップ3がハングし、その他の処理はすべて終了します。

私の質問は、処理が必要なファイルごとに正確に1つのスレッドを生成する正しいパラダイムは何か、1つのファイルが長時間かかる場合はブロックしないのですか?私はFileSystemWatcherと考えましたが、ファイルがすぐに読み込めない場合があります。なぜなら、私は常にすべてのファイルを見て、それぞれのプロセスを生成しているからです(ファイルがロックされているとすぐに終了します)。

手順3を削除して、すでに処理したファイルのリストを維持する必要がありますか?それは厄介で、リストは時間の経過とともに非常に大きくなるので、より洗練されたソリューションがあると思われます。

+0

処理後のファイルはどうなりますか?それは同じディレクトリに残っていますか?削除?動いた?また、サーバディレクトリにダンプされたファイルは、同じ拡張子で一貫して名前が付けられていますか? – gangelo

+0

上記のプロセスがファイルが2回処理されないように私は理解していません。 –

+0

ファイルが処理された後、ステップ#2で削除されたので、ステップ#3が完了すると、そのフォルダ内のファイルは処理され、以前に処理されていません。 – powlette

答えて

6

現在処理しているファイルのリストを維持することをお勧めします。スレッドが終了したときにスレッドをこのリストから削除させる。新しいファイルを探すときは、現在実行中のリストのファイルを除外します。

+0

どのファイルがスレッドキューから削除された後に処理されたかをどのように追跡しますか? – gangelo

+0

彼はすでにこの問題を抱えているので、これは、たとえば、プロセスの最後に削除されたファイルなどですでに解決されていると仮定します。 –

+0

はい、これは本質的に私が考えていたことです。自分のものを転がすのではなく、試行錯誤した既存のプロデューサー/消費者パラダイムが存在することを期待していました。ありがとう。 – powlette

3

スレッドを開始する前にファイルを処理ディレクトリに移動します。その後、スレッドを消して忘れることができ、管理者は何が起こっているか一目で見ることができます。

+0

これはサーバーでもこれを行うことができると仮定していますが、私はこのアイデアが好きです。なぜなら、それぞれのディレクトリに置かれているためにどのファイルを処理する必要があるのか​​を知っているからです。 – gangelo

3

処理するアイテムごとに1つのスレッドを生成することは、ほとんど決して良いアプローチではありません。あなたのケースでは、ファイル数が数百を超えると、1つのファイルあたり1スレッドでアプリケーションのパフォーマンスがかなり悪くなり、32ビットプロセスではアドレス空間が使い果たされます。

ダークファルコンによるリストソリューションは簡単で、アルゴリズムに合っています。私は実際にアイテムを(つまり、ファイルウォッチャーの定期的なスキャンに基づいて)処理し、もう一方の側で1つまたは複数のスレッドで処理するアイテムを選択するためにキュー(ConcurrentQueue - http://msdn.microsoft.com/en-us/library/dd267265.aspx)を使用します。一般にスレッドの数(CPUの負荷が重くなると1〜2倍のCPU数)が必要になります。

複数のスレッドを処理するために、タスクパラレルライブラリ(Parallel.ForEach - http://msdn.microsoft.com/en-us/library/dd989744.aspxなど)を使用することも検討してください。

処理するファイルの数を最小限に抑えるため、ファイルパス+最終変更日(他のソースからこの情報を取得できない場合)を、永続的(つまりディスクファイル)のリストに保存します。

1

私の二つの主な質問は次のようになります。

  1. ファイルのサイズは何ですか?
  2. ファイルはどのくらいの頻度で表示されますか?

があなたの答えに応じて、私は以下の生産者 - 消費者のアルゴリズムで行くかもしれないが:

  1. あなたは
  2. ときを監視しているディレクトリ内のアクティビティがあることを確認するために、ファイルシステムウォッチャーを使用しますアクティビティが発生した場合、「軽く」ポーリングを開始します。ロックされていないかどうかを調べるために各ファイルをテストします(つまり、試してテストする単純なIsLocked拡張メソッドを使用して書き込み権限を開いてみてください)。キャッチ); 1つ以上のファイルが空いていない場合は、一定時間内にタイマーをオフにするようにタイマーを設定します(ファイルが大きくなると予想される時間は長くなりますが、小さければ時間が短くなります)。ファイルを自由に処理します(つまり、別のフォルダに移動し、並行キューにアイテムを入れ、コンシューマスレッドがキューを処理し、ファイル/結果をアーカイブします)。
  3. システム障害が発生した場合に処理を中断した場合に、アレクセイ(Alexei)のような永続化メカニズム(ディスク/データベースなど)を使用して処理を回復することができます。

これは、ノンブロッキングで、CPU使用率が低いという優れた組み合わせだと思います。しかし、前と後の結果を測定します。

  1. ベースの数:私はThreadPoolのを使用することをお勧めし、ブロッキングのスレッドを維持しようとする

    ノート(すなわち、のThread.sleepのようなものを実行してブロックしていないことで、スレッドの再利用性を確保しようとします)マシン上で利用可能なCPUおよびコアの数に関するファイルを処理するスレッド。サーバーの負荷も考慮する

  2. FileSystemWatcherは厄介なことがあります。監視しているマシン(リモートサーバーを監視していないマシン)から実行されていることを確認してください。そうでない場合は、接続を再初期化する必要があります。
  3. ファイルごとに異なるプロセスを作成するのは間違いありません。複数のスレッドで十分なはずです。スレッドを再利用するのが最適です。産卵プロセスは非常に高価な操作であり、スレッドの産卵は高価な操作です。 Alexeiには、タスク並列ライブラリに関するいくつかの優れた情報があります。それはThreadPoolを使用します。
関連する問題