C# - 始终运行和Dequeing的队列管理

时间:2012-03-26 09:00:36

标签: c# queue

我需要构建一个在WCF中侦听新任务的进程。 (异步) 每个任务都得到入队(不知何故)。

循环队列并将其出列的最佳(逻辑和性能)方法是什么。

我想到了:

while(true){
   queue.Dequeue();
}

我认为有更好的方法可以做到这一点。

由于

2 个答案:

答案 0 :(得分:7)

查看System.Collections.Concurrent命名空间 - 有线程安全队列实现即。 ConcurrentQueue - 尽管如此,我怀疑BlockingCollection可以更好地满足您的需求。

阻塞集合本质上是一个对生产者 - 消费者场景有用的线程安全集合。在您的情况下,WCF调用将充当将添加到集合的生成器,而工作线程将充当将基本上从集合中排队的任务的消费者。通过使用单个使用者(和集合),您可以确保执行顺序。如果这不重要,那么您可以使用多个消费者线程。 (还有AddAnyTakeAny静态重载,如果需要,可以使用多个集合(多个队列)。)

优于while(true)方法的优点是避免仅占用CPU周期的紧密循环。除了具有线程安全性之外,这还将解决排队和排队线程之间的同步问题。

修改

阻止收藏真的很简单易用。请参阅下面的简单示例 - 在调用服务启动期间调用StartConsumer时,将调用添加任务来说明您的WCF方法以排队任务。

public class MyTask { ... }

private BlockingCollection<MyTask> _tasks = new BlockingCollection<MyTask>();

private void AddTask(MyTask task)
{
  _tasks.Add(task);
}

private void StartConsumer()
{
   // I have used a task API but you can very well launch a new thread instead of task
   Task.Factory.StartNew(() =>
     {
        while (!_tasks.IsCompleted)
        {
            var task = _tasks.Take();
            ProcessTask(task);
        }
     });
}

在停止服务时,需要调用_tasks.CompleteAdding以便消费者线程中断。

在MSDN上查找更多示例:

http://msdn.microsoft.com/en-us/library/dd997306.aspx
http://msdn.microsoft.com/en-us/library/dd460690.aspx
http://msdn.microsoft.com/en-us/library/dd460684.aspx

答案 1 :(得分:0)

我会使用事件来同步队列,而不是无限循环。无论何时进行WCF调用,都要向队列中添加一个元素并发送一个“AnElementHasBeenAddedEvent”。

执行排队任务的线程侦听该事件,每当收到该事件时,队列将被清空。

确保只有一个线程可以完成这项工作!

优于while(true)概念的优点:您没有一个不断循环遍历无限循环并因此占用资源的线程。你只需要做很多工作。