はい、もちろん、これは生産者と消費者のモデルのバリエーションです。
Thread
ここでは、 やのようないくつかの基本的なビルディング ブロックを使用できますAutoResetEvent
。「プロデューサー」はログから行を読み取り、それらをファイルに投稿し (代わりにメモリ内バッファーを使用できますか?)、他のスレッドにそれらを読み取るように通知します。
AutoResetEvent consumerEvent = new AutoResetEvent(false);
AutoResetEvent producerEvent = new AutoResetEvent(false);
// producer code
while(/* lines still available */)
{
// read 500 lines
// write to shared file
consumerEvent.Set(); // signal consumer thread
producerEvent.WaitOne(); // wait to be signaled to continue
}
そして消費者コード:
while(/* termination not received */)
{
consumerEvent.WaitOne(); // wait for the producer to finish
// read lines from file and put them in the grid
producerEvent.Set(); // allow producer to read more logs
}
これにより、ファイルを読み取るコンシューマーと、さらにログを読み取り、次のバッチを準備するプロデューサーとの間で、ある程度の並列処理が可能になります。
プロデューサーがログの処理を終了すると、ファイルに特別な終了メッセージを入れて、正常に終了するようにコンシューマーに通知できます。
これは 1 つの戦略であり、かなり低レベルでエラーが発生しやすいものです。共有ファイルを完全にスキップして、BlockingCollectionの形式でメモリ内バッファを使用できます。
ProducerTask
数行のテキストを保持するクラスを定義します。
class ProducerTask
{
public String[] Lines { get; set; }
}
このタスクは一度に 500 行を保持します。
次に、次のようTask
に and BlockingCollection
(.NET 4.0+) を使用します。
BlockingCollection<ProducerTask> buffer = new BlockingCollection<ProducerTask>(1);
// producer task
while(/* lines still available */)
{
// read 500 lines
ProducerTask p = new ProducerTask();
buffer.Add(p); // this will block until the consumer takes the previous task
}
// consumer task
while(/* termination not received */)
{
ProducerTask p = buffer.Take(); // blocks if no task is available
// put the lines in the grid
}
はるかにシンプルでエレガント。