从C#中的ConcurrentQueue中排队对象

时间:2010-08-17 13:30:04

标签: c# .net

嘿,我正在尝试在C#中为异步服务器实现ConcurrentQueue。收到完整的消息后,项目将排队。为了使消息出列,我正在制作少量线程来执行出列和服务请求的工作。这是不够的,因为每个线程都使用while循环,这显然会消耗相当多的处理器时间。

有人知道在需要时出现消息的方法,但不会消耗太多的处理时间。

{
    ...

    for (int i = 0; i < 3; i++)
    {
        Thread t = new Thread(new ThreadStart(startParsingMessages));
        t.Start();
    }

    ...
}

private void startParsingMessages()
{
    QueueContainer dequeued = null;
    Console.WriteLine("Trying");
    while (true)
    {
        if (queue.TryDequeue(out dequeued))
        {
            Console.WriteLine("processing queue");
            ProcessMessage(dequeued.socket, dequeued.message);
        }
    }
}

3 个答案:

答案 0 :(得分:20)

您是否尝试将其包裹在BlockingCollection<T>中,而不是直接使用ConcurrentQueue<T>?然后你可以使用TryTake(out T, TimeSpan)等。我相信这是预期的用途:并发集合本身通常就在那里你可以选择阻塞集合的工作方式。

当然,这不一定是用于这些集合,但特别是对于ConcurrentQueue<T>,生产者/消费者队列场景是最常见的 - 在这一点上BlockingCollection<T>是让你做正确事情变得容易的方法。

答案 1 :(得分:5)

在并发编程中有一个非常清楚的模式叫做Parallel Producer / Consumer模式。本文可能有助于解决您的一些问题。 http://blogs.msdn.com/b/csharpfaq/archive/2010/08/12/blocking-collection-and-the-producer-consumer-problem.aspx

答案 2 :(得分:3)

您可以使用静态锁定对象让线程等待,然后在准备好处理某些内容时对其进行脉冲。

static readonly object queueLock = new object();

// Threads that enqueue an object
void QueueMessage() {
  lock (queueLock) {
    queue.Enqueue(obj);
    Monitor.Pulse(queueLock);
  }
}
// Thread dequeuer
private void startParsingMessages() {
  QueueContainer dequeued = null;
  Console.WriteLine("Trying");
  while (true) {
    lock(queueLock) {
      if (!queue.TryDequeue(out dequeued)) {
        Console.WriteLine("No object to dequeue, waiting...");
        // Threads will wait here and only one will be released when .Pulse()d
        Monitor.Wait(queueLock);
        dequeued = queue.Dequeue();
      }
      if (dequeued != null) {
        Console.WriteLine("processing queue");
        ProcessMessage(dequeued.socket, dequeued.message);
      }
    }
  }
}

请记住,随着分支越多,这会变得非常复杂,但要点是,你锁定一个公共对象并调用Monitor.Wait等待一个对象{{1} } d。当发生这种情况时,只有一个等待它的线程将被释放。如果你将许多对象排入队列并且希望它们全部被删除,你可以调用Pulse来释放所有在对象上等待的线程。