【问题标题】:How to have many consumer threads using BlockingCollection如何使用 BlockingCollection 拥有多个消费者线程
【发布时间】:2013-07-31 19:07:07
【问题描述】:

我正在使用由 BlockingCollection 支持的生产者/消费者模式来从文件中读取数据,解析/转换然后插入到数据库中。我拥有的代码与此处的代码非常相似:http://dhruba.name/2012/10/09/concurrent-producer-consumer-pattern-using-csharp-4-0-blockingcollection-tasks/

但是,主要区别在于我的消费者线程不仅解析数据,还插入到数据库中。这个有点慢,我认为是导致线程阻塞。

在示例中,有两个消费者线程。我想知道是否有办法以某种智能的方式增加线程数?我原以为线程池可以做到这一点,但似乎无法理解如何做到这一点。

另外,您将如何选择消费者线程的数量? 2 对我来说似乎不正确,但我不确定最好的 # 会是什么。对选择 # 个消费者线程的最佳方式有何想法?

【问题讨论】:

  • 线程并不是每个性能问题的神奇解决方案。添加更多往往会创建更多等待线程或不喜欢您的应用程序完全占用服务器的生气的 dbase 管理员。
  • 此应用程序将在计划的停机时间内运行,因此数据库命中是可以接受的。我只是想尽量减少停机时间。
  • 这是否与午夜的停机时间有关,您只是不想坚持那么久来尝试它?
  • 好吧,我不会一直呆到午夜,但我想让他们的生活更轻松!

标签: c#-4.0 producer-consumer


【解决方案1】:

选择消费者线程数量的最佳方法是数学:计算每分钟有多少数据包来自生产者,然后除以单个消费者每分钟可以处理的数据包数量,你就有了一个相当不错的结果了解您需要多少消费者。

我通过添加另一个BlockingCollection 解决了阻塞输出问题(消费者在尝试更新数据库时阻塞),消费者将完成的数据包放入其中。一个单独的线程读取该队列并更新数据库。所以它看起来像:

input thread(s) => input queue => consumer(s) => output queue => output thread

这具有将消费者与输出分离的额外好处,这意味着您可以优化输出或完全改变输出方法而不影响消费者。例如,这可能允许您批量更新数据库,这样您就可以通过一次调用更新十几个或一百个(或更多)记录,而不是对每条记录进行一次数据库调用。

我在我的文章Simple Multithreading, Part 2 中展示了一个非常简单的示例(使用单个消费者)。这适用于文本文件过滤器,但概念是相同的。

【讨论】:

  • 这太棒了!批处理数据库更新听起来正是我所需要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多