嘿,我正在尝试在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);
}
}
}
答案 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
来释放所有在对象上等待的线程。