使用BlockingCollection <t>作为单生成器,单用户FIFO查询是不是很好?</t>

时间:2012-04-11 09:15:13

标签: c# .net multithreading .net-4.0 producer-consumer

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

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

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

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

我的任务有多适合BlockingCollection,可能你可以提出别的建议吗?

2 个答案:

答案 0 :(得分:11)

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

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

使用TPL TasksBlockingCollection生成者 - 消费者样本申请:

class ProducerConsumer
{
    private static BlockingCollection<string> queue = new BlockingCollection<string>();

    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)可以使用   集合作为底层存储机制。

答案 1 :(得分:0)

既然你需要一个队列,为什么不坚持队列呢?您可以使用Syncrhonized Queue