Pri*_*rix 12 c# multithreading concurrent-collections
什么是正确的使用,BlockingCollection或者ConcurrentQueue你可以自由地出列项目,而不会使用一个线程烧掉一半或更多的CPU?
我使用2个线程运行一些测试,除非我有一个至少50~100ms的Thread.Sleep,它总是至少达到我CPU的50%.
这是一个虚构的例子:
private void _DequeueItem()
{
object o = null;
while(socket.Connected)
{
while (!listOfQueueItems.IsEmpty)
{
if (listOfQueueItems.TryDequeue(out o))
{
// use the data
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过上面的例子,我将不得不设置一个thread.sleep,以便cpu不会爆炸.
注意:我也尝试了没有用于IsEmpty检查的时间,结果是一样的.
Jal*_*aid 22
这不是因为BlockingCollectionor ConcurrentQueue,而是while循环:
while(socket.Connected)
{
while (!listOfQueueItems.IsEmpty)
{ /*code*/ }
}
Run Code Online (Sandbox Code Playgroud)
当然会降低cpu; 因为如果队列是空的,那么while循环就像:
while (true) ;
Run Code Online (Sandbox Code Playgroud)
反过来会占用cpu资源.
这不是一个ConcurrentQueue使用AutoResetEvent它的好方法,因此无论何时添加项目,您都会收到通知.例:
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
}
}
Run Code Online (Sandbox Code Playgroud)
为了更好地使用BlockingCollection你应该使用GetConsumingEnumerable()等待添加的项目,如:
//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.
}
Run Code Online (Sandbox Code Playgroud)
BlockingCollection在这种情况下,你真的想要使用该类.它被设计为阻塞,直到项目出现在队列中.这种性质的集合通常被称为阻塞队列.这种特定的实现对于多个生产者和多个消费者是安全的 如果你自己尝试实现它,那就很难做到.以下是您使用时代码的外观BlockingCollection.
private void _DequeueItem()
{
while(socket.Connected)
{
object o = listOfQueueItems.Take();
// use the data
}
}
Run Code Online (Sandbox Code Playgroud)
Take如果队列为空,则该方法自动阻止.它以一种将线程置于SleepWaitJoin状态的方式阻塞,以便它不会消耗CPU资源.巧妙的BlockingCollection是它还使用低锁策略来提高性能.这意味着Take将检查队列中是否有项目,如果没有,那么它将暂时执行旋转等待以防止线程的上下文切换.如果队列仍为空,那么它将使线程进入休眠状态.这意味着BlockingCollection它将具有一些ConcurrentQueue与并发执行相关的性能优势.
| 归档时间: |
|
| 查看次数: |
6281 次 |
| 最近记录: |