2

我已经阅读了一些其他类似但不相同的链接,试图找到一些答案: 如何批量使用 BlockingCollection<T>

但是,(在上面的链接中)不使用 GetConsumingEnumerable 似乎很可疑。

当消费者(应该是单数)清空集合时,有效阻止生产者的正确方法是什么?

[我们想要进行批处理,因为每个批处理都会执行一个 Web 服务调用,如果每条消息/项目都需要自己的调用,这将是一个瓶颈。批处理消息/项目是解决此瓶颈的方法。]

理想情况下:

1) 接收消息

2) 新的生产者任务推入收集

3)当集合“满”(任意限制)时,阻塞所有生产者,新的消费者任务消耗所有集合,然后为生产者解除阻塞。

换句话说; 我希望(并行生产者)xor(单一消费者)随时对集合起作用。

似乎以前应该这样做过,但我似乎找不到专门以这种方式运行的代码片段。

谢谢你的帮助。

4

2 回答 2

0

根据您的模糊描述,我相信双缓冲是您想要的。

只需创建两个缓冲区。生产者写入一个直到。当它变满或计时器计时结束时,它会被“交换”到第二个,并且生产者开始写入新的。然后消费者开始读取第一个,现在是完整的缓冲区。

这允许生产者和消费者同时运行。并确保消费者在再次重复循环之前批量处理所有先前创建的工作。

于 2015-04-07T04:36:46.173 回答
0

使用这个模型,所有的工作都是完全序列化的,也就是说你一次不会有超过一个“东西”在工作。要么生产者在工作,要么消费者在工作。正因为如此,您实际上并不需要一个由生产者和消费者共同操作的集合,相反,您可以拥有一个生产者来生成批量的传统集合,供消费者在完成时使用。它可能看起来像这样:

public Task<List<Thing>> Produce(Message message)
{
    //...
}

public Task Consume(List<Thing> data)
{
    //...
}

public async Task MessageReceived(Message message)
{
    while(HaveMoreBatches(message))
    {
        await Consume(await Produce(message));
    }
}

这使您可以生产一批,然后消费它,然后生产另一批,然后消费它,等等,直到没有更多的批次要生产。

于 2015-04-06T20:19:22.457 回答