将BlockingCollection 用作单生成器,单用户FIFO查询是否合适?

我需要单生成器,单用户FIFO查询,因为

  • 我需要按照收到的顺序处理邮件。
  • 我需要这样做异步,因为调用者不应该在我处理消息时等待。
  • 只有在完成上一个消息处理时,才应启动下一个消息处理。 有时“接收”消息的频率高于“处理”消息的频率。 但平均而言,我应该能够处理所有消息,有时候我必须“排队”它们。

所以它就像我认为的TCP / IP,你有一个生产者和一个消费者,有时你可以比你可以处理的更快地接收消息,所以你必须查询它们。 在哪里订单很重要,并且调用者对你用这些东西做什么完全不感兴趣。

这听起来很容易,我可能会使用通用Queue ,但我想使用BlockingCollection ,因为我不想用ManualResetEvent等编写任何代码。

BlockingCollection对我的任务有多适合,可能你还可以推荐别的东西?

BlockingCollection类实现了IProducerConsumerCollection接口,因此完全符合您的要求。

您可以创建两个任务,一个用于异步生产者,另一个用作消费者工作者。 前者会将项目添加到BlockingCollection ,后者只要在FIFO顺序中有新的项目时就会消耗。

使用TPL任务和BlockingCollection的生产者 – 消费者样本应用程序:

 class ProducerConsumer { private static BlockingCollection queue = new BlockingCollection(); static void Main(string[] args) { Start(); } public static void Start() { var producerWorker = Task.Factory.StartNew(() => RunProducer()); var consumerWorker = Task.Factory.StartNew(() => RunConsumer()); Task.WaitAll(producerWorker, consumerWorker); } private static void RunProducer() { int itemsCount = 100; while (itemsCount-- > 0) { queue.Add(itemsCount + " - " + Guid.NewGuid().ToString()); Thread.Sleep(250); } } private static void RunConsumer() { foreach (var item in queue.GetConsumingEnumerable()) { Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.ffff") + " | " + item); } } } 

IProducerConsumerCollection :

定义操作用于生产者/消费者使用的线程安全集合的方法。 此接口为生产者/消费者集合提供统一表示,以便更高级别的抽象(如System.Collections.Concurrent.BlockingCollection(Of T))可以将集合用作底层存储机制。

因为它是你需要的队列,为什么不坚持队列? 您可以使用Syncrhonized Queue 。