1

バッチ

  1. ファイルまたは SQL からテキストを読み取る
  2. テキストを単語に解析する
  3. 単語を SQL にロードする

現在、
.NET 4.0
のステップ 1 は非常に高速です。ステップ 2 と 3 は、同じサイズのファイルに対してほぼ同じ長さ (平均 0.1 秒) です。
ステップ 3 で BackGroundWorker を使用して挿入し、最後が完了するまで待ちます。
他のすべてはメインスレッドにあります。

大きな負荷では、これが数百万回行われます。

ステップ 3 は 1 と同じ順番でシリアルにする必要があります。
これは、SQL テーブルの PK インデックスが壊れないようにするためです。
ステップ 3 を並行して試行し、インデックスをフラクチャすると強制終了しました。
このデータは、PK でソートされて供給されます。
他のインデックスはロードの開始時に削除され、ロードの終了時に再構築されます。

このプロセスが効果的でないのは、テキストのサイズが変わる場合です。
また、ファイルからファイルへのテキストのサイズは大幅に変化します。
私が望むのは、1 と 2 をキューに入れ、3 ができるだけビジーになるようにすることです。

1 でキューに入れられた順序でファイルをデキューするには、ステップ 3 が必要です (待機していても)。

メモリ管理のために最大キュー サイズが必要です (4 ~ 10 など)。

ステップ 2 を最大 4 つの同時並行で実行したいと考えています。

.NET 4.5 への移行。

これを実装する方法に関する一般的なガイダンスを求めていますか?

これが生産者消費者パターンであることを学んでいます。
これが生産者と消費者のパターンでない場合は、タイトルを変更できるようにお知らせください。

4

1 に答える 1

2

これを行うには、TPL Dataflow が良い方法だと思います。

ステップ 2 では、 4 に設定した aTransformBlockを使用し、さらに 4に設定して、作業時にそのキューが空になるようにします。入ったときと同じ順序でアイテムが生成されます。そのために特別なことをする必要はありません。ステップ 3 では、制限に設定された, を使用します。次に、この 2 つをリンクして、アイテムの への送信を開始します。理想的には のようなものを使用して、キューがいっぱいになった場合に非同期的に待機します。MaxDegreeOfParallelismBoundedCapacityActionBlockBoundedCapacityTransformBlockawait stepTwoBlock.SendAsync(…)

コードでは、次のようになります。

async Task ProcessData()
{
    var stepTwoBlock = new TransformBlock<OriginalText, ParsedText>(
        text => Parse(text),
        new ExecutionDataflowBlockOptions
        {
            MaxDegreeOfParallelism = 4,
            BoundedCapacity = 4
        });
    var stepThreeBlock = new ActionBlock<ParsedText>(
        text => LoadIntoDatabase(text),
        new ExecutionDataflowBlockOptions { BoundedCapacity = 10 });
    stepTwoBlock.LinkTo(
        stepThreeBlock, new DataflowLinkOptions { PropagateCompletion = true });

    // this is step one:
    foreach (var id in IdsToProcess)
    {
        OriginalText text = ReadText(id);
        await stepTwoBlock.SendAsync(text);
    }

    stepTwoBlock.Complete();
    await stepThreeBlock.Completion;
}
于 2012-10-16T18:00:41.540 に答える