1

  1. 从文件或 SQL 中读取文本
  2. 将文本解析为单词
  3. 将单词加载到 SQL 中

今天
.NET 4.0
Step 1 非常快。对于相同大小的文件,步骤 2 和 3 的长度大致相同(平均 0.1 秒)。
在第 3 步中,使用 BackGroundWorker 插入并等待最后一个完成。
其他一切都在主线程上。

在大负载上将执行数百万次。

需要步骤 3 是连续的,并且与 1 的顺序相同。
这是为了防止 SQL 表 PK 索引破裂。
并行尝试第 3 步并破坏索引将其杀死。
该数据由 PK 排序馈送。
其他索引在加载开始时被删除,然后在加载结束时重建。

当文本大小发生变化时,此过程无效。
文件之间的文本大小确实发生了巨大变化。
我想要的是让 1 和 2 排队,以便 3 尽可能保持忙碌。

需要步骤 3 将文件出列,以便它们在 1 中排队(即使它等待)。

需要内存管理的最大队列大小(如 4-10)。

希望第 2 步与最多 4 个并发并行。

迁移到 .NET 4.5。

要求有关如何实施此操作的一般指导?

我正在学习这是一种生产者消费者模式。
如果这不是生产者消费者模式,请告诉我,以便我更改标题。

4

1 回答 1

2

我认为 TPL Dataflow 将是做到这一点的好方法:

对于第 2 步,您将使用TransformBlock设置MaxDegreeOfParallelism为 4 并BoundedCapacity设置为 4 的 a,以便其队列在工作时为空。它会按照它们进来的顺序生产物品,你不必为此做任何特别的事情。对于第 3 步,使用ActionBlock, 并BoundedCapacity设置为您的限制。然后将两者链接在一起并开始向 发送项目TransformBlock,理想情况下使用类似的东西await 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 回答