处理消息队列的C#线程
我有以下要求-处理消息队列的C#线程,c#,multithreading,message-queue,C#,Multithreading,Message Queue,我有以下要求- 接收消息并将其排队的线程 处理排队消息的线程 现在,第二个线程必须始终处于活动状态-为此,我使用了无限while循环,如下所示: private AutoResetEvent messageReset; private Queue<byte[]> messageQueue; //thread 2 method private void ProcessIncomingMessages() { messageReset.WaitOne(); //wait for si
private AutoResetEvent messageReset;
private Queue<byte[]> messageQueue;
//thread 2 method
private void ProcessIncomingMessages()
{
messageReset.WaitOne(); //wait for signal
while(true)
{
if (messageQueue.Count > 0)
{
//processing messages
}
}
}
public void SubmitMessageForProcessing(byte[] message){
messageQueue.Enqueue(message); //enqueue message
// Release the thread
messageReset.Set();
}
private AutoResetEvent messageReset;
专用队列消息队列;
//线程2方法
私有void ProcessIncomingMessages()
{
messageReset.WaitOne();//等待信号
while(true)
{
如果(messageQueue.Count>0)
{
//处理消息
}
}
}
用于处理的公用void SubmitMessage(字节[]消息){
messageQueue.Enqueue(message);//Enqueue message
//脱线
messageReset.Set();
}
现在,这个无限while循环的CPU利用率非常高。
是否有降低CPU利用率的解决方法
注意:我无法添加任何thread.sleep语句,因为传入消息将以最小延迟显示在UI上。在您的示例中,
while
循环将一直忙到队列至少有一个元素为止。您可以将信号移动到该循环中,以减少繁忙的等待并使用更少的CPU
private void ProcessIncomingMessages()
{
while(true)
{
messageReset.WaitOne(100); //wait for signal
while (messageQueue.Count > 0)
{
//processing messages
}
}
}
另外,除非您有某种自定义的锁定机制,否则如果您希望线程安全,必须使用ConcurrentQueue
而不是队列。另外,我在WaitOne调用上设置了一个超时,因为在您检查计数之后,但在到达WaitOne调用之前,设置信号的可能性很小。解决方案中可能存在其他线程问题。如果您对线程问题没有信心,您可能希望使用a,它会为您处理很多细节。只需使用a而不是队列。它是线程安全的,将在Take
上阻塞,直到有工作人员添加一个项目:
// Use default constructor to make BlockingCollection FIFO
private BlockingCollection<byte[]> messageQueue = new BlockingCollection<byte[]>();
//thread 2 method
private void ProcessIncomingMessages()
{
while (true)
{
//will block until thread1 Adds a message
byte[] message = messageQueue.Take();
//processing messages
}
}
public void SubmitMessageForProcessing(byte[] message)
{
messageQueue.Add(message); //enqueue message
}
//使用默认构造函数生成BlockingCollection FIFO
private BlockingCollection messageQueue=new BlockingCollection();
//线程2方法
私有void ProcessIncomingMessages()
{
while(true)
{
//将一直阻止,直到thread1添加消息
byte[]message=messageQueue.Take();
//处理消息
}
}
用于处理的公用void SubmitMessage(字节[]消息)
{
messageQueue.Add(message);//将消息排队
}
EDIT2:我忘了提到,通过使用BlockingCollection
将是FIFO。它实际上将使用ConcurrentQueue
作为项目容器
如果希望BlockingCollection
的行为类似于后进先出集合,则需要将后进先出的集合传递给构造函数。通常的课程是
编辑:解释一下您的队列如何不是线程安全的,这可能会导致当前代码出现问题
从队列上的Microsoft文档中
:
只要不修改集合,队列可以同时支持多个读取器
这意味着您不能同时读取和写入多个线程
请看下面的示例,该示例也适用于建议在while(true)
块中移动messageReset.WaitOne()
SubmitMessageForProcessing
被调用,并发出信号messageReset.Set()
线程2处于活动状态并尝试读取数据
当线程2读取数据SubmitMessageForProcessing
时,调用第二次
现在你同时写和读导致了意想不到的行为(通常是某种异常)
您可能想了解一下,它是线程安全的,并且阻止了Take
谢谢。。你能详细说明一下螺纹的安全性吗。BlockCollection中的线程安全性如何优于Queue中的线程安全性。@HershikaSharma文档中的threadsafety部分可能会比我做更好的解释。但是,如果某些特定的东西不清楚,不要担心问。嗨,弗雷格,阻止收集是否遵循FIFO?下面的场景将如何实现-@HershikaSharma问得好,我实际上忘了提到这一点!是的,BlockingCollection
是在使用默认构造函数时。但是它也可以用作后进先出。@HershikaSharma你是对的,BlockingCollection
使用了IProducerConsumerCollection
界面/模式,设计上不允许偷看。如果您需要该功能,很遗憾您不能使用BlockingCollection
。如果您真的需要这种行为,我将从