没有Thread.Sleep的并发集合吃了太多的cpu [英] Concurrent collections eating too much cpu without Thread.Sleep

查看:216
本文介绍了没有Thread.Sleep的并发集合吃了太多的cpu的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

BlockingCollectionConcurrentQueue的正确用法是什么,以便您可以自由地使项目出队,而不会使用线程消耗掉一半或更多的CPU?

What would be the correct usage of either, BlockingCollection or ConcurrentQueue so you can freely dequeue items without burning out half or more of your CPU using a thread ?

我正在使用2个线程运行一些测试,除非我的Thread.Sleep至少为50〜100ms,否则它至少会占用我CPU的50%.

I was running some tests using 2 threads and unless I had a Thread.Sleep of at least 50~100ms it would always hit at least 50% of my CPU.

这是一个虚构的例子:

private void _DequeueItem()
{
    object o = null;
    while(socket.Connected)
    {
        while (!listOfQueueItems.IsEmpty)
        {
            if (listOfQueueItems.TryDequeue(out o))
            {
                // use the data
            }
        }
    }
}

在上面的示例中,我将必须设置一个thread.sleep,这样CPU才不会崩溃.

With the above example I would have to set a thread.sleep so the cpu doesnt blow up.

注意:我也尝试了一段时间而不进行IsEmpty检查,结果是一样的.

Note: I have also tried it without the while for IsEmpty check, result was the same.

推荐答案

不是因为BlockingCollectionConcurrentQueue,而是while循环:

It is not because of the BlockingCollection or ConcurrentQueue, but the while loop:

while(socket.Connected)
{
    while (!listOfQueueItems.IsEmpty)
    { /*code*/ }
}

当然,这会降低CPU的性能;因为如果队列为空,则while循环就像:

Of course it will take the cpu down; because of if the queue is empty, then the while loop is just like:

while (true) ;

反过来会占用CPU资源.

which in turn will eat the cpu resources.

这不是使用ConcurrentQueue的好方法,您应该将其与AutoResetEvent一起使用,因此无论何时添加项目,您都会收到通知. 示例:

This is not a good way of using ConcurrentQueue you should use AutoResetEvent with it so whenever item is added you will be notified. Example:

private ConcurrentQueue<Data> _queue = new ConcurrentQueue<Data>();
private AutoResetEvent _queueNotifier = new AutoResetEvent(false);

//at the producer:
_queue.Enqueue(new Data());
_queueNotifier.Set();

//at the consumer:
while (true)//or some condition
{
    _queueNotifier.WaitOne();//here we will block until receive signal notification.
    Data data;
    if (_queue.TryDequeue(out data))
    {
        //handle the data
    }
}

为了充分利用BlockingCollection,您应该使用GetConsumingEnumerable()等待添加项,例如:

For a good usage of the BlockingCollection you should use the GetConsumingEnumerable() to wait for the items to be added, Like:

//declare the buffer
private BlockingCollection<Data> _buffer = new BlockingCollection<Data>(new ConcurrentQueue<Data>());

//at the producer method:
_messageBuffer.Add(new Data());

//at the consumer
foreach (Data data in _buffer.GetConsumingEnumerable())//it will block here automatically waiting from new items to be added and it will not take cpu down 
{
    //handle the data here.
}

这篇关于没有Thread.Sleep的并发集合吃了太多的cpu的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆