.Net中的ConcurrentQueue和BlockingCollection有什么区别?

Tam*_*ran 49 .net generics c#-4.0

.Net 之间ConcurrentQueue和之间有什么区别BlockingCollection

为什么BlockingCollection最好的生产者 - 消费者操作可以通过ConcurrentQueue?我是否必须改进以下代码中的任何内容?

MessageSlotMachineGameStartOrAndStatusUpdate msg;

while (!aCancellationToken.IsCancellationRequested)
{
    try
    {
        this.isStillConsumingMsg = true;
        Boolean takeResult = this.msgQueue.TryTake(out msg, this.msgConsumeTimeOut, aCancellationToken);
        if (takeResult)
        {
            if (msg != null)
            {
                this.ProcessMessage(msg);
            }
        }
        else
        {
            break;
        }
    }
    catch (OperationCanceledException err)
    {
        EngineManager.AddExceptionLog(err, "Signal Operation Canceled");
    }
    catch (Exception err)
    {
        EngineManager.AddExceptionLog(err, "Signal exception");
    }
    finally
    {
        this.isStillConsumingMsg = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

das*_*ght 50

BlockingCollection有一种Take方法可以阻止消费者,如果没有什么可以采取,并等待生产者方提供一个项目.ConcurrentQueue缺少这样的方法 - 如果它是空的,消费者将需要处理等待,并且生产者需要提供非空通知.

  • @WAPGuy 您可以使用 [`AutoResetEvent`](http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx)。点击链接并向下滚动查看如何使用它的示例。 (2认同)

Elo*_*Elo 11

BlockingCollection是并发集合包装,默认包裹集合是一个ConcurrentQueue ;-)

来自Microsoft BlockingCollection

创建 BlockingCollection 对象时,您不仅可以指定有界容量,还可以指定要使用的集合类型。例如,您可以为先进先出 (FIFO) 行为指定ConcurrentQueue对象,或为后进先出 (LIFO) 行为指定ConcurrentStack对象。您可以使用任何实现IProducerConsumerCollection接口的集合类。 BlockingCollection 的默认集合类型是 ConcurrentQueue。

BlockingCollection采取()阻塞法(因此得名),但它也有一个非常有趣的GetConsumingEnumerable()方法,它可以让你无限循环:代码将进入里面的代码回路只有当事情被添加到收藏。请参阅albahari.com优秀的关于线程的在线电子书。

这是来自该网站的代码示例:

public class PCQueue : IDisposable
{
  BlockingCollection<Action> _taskQ = new BlockingCollection<Action>(); 
  public PCQueue (int workerCount)
  {
    // Create and start a separate Task for each consumer:
    for (int i = 0; i < workerCount; i++)
      Task.Factory.StartNew (Consume);
  }
 
  public void Dispose() { _taskQ.CompleteAdding(); }
 
  public void EnqueueTask (Action action) { _taskQ.Add (action); }
 
  void Consume()
  {
    // This sequence that we’re enumerating will block when no elements
    // are available and will end when CompleteAdding is called. 
    foreach (Action action in _taskQ.GetConsumingEnumerable())
      action();     // Perform task.
  }
}
Run Code Online (Sandbox Code Playgroud)