C# - 队列管理,保证队列始终运行并出队

3

我需要构建一个监听WCF新任务的过程。(异步)每个任务都会被排队(某种方式)。

最好的(逻辑和性能)方式是循环队列并将其出队。

我想过:

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

我想应该有更好的方法来做这件事情。谢谢。
2个回答

8
请查看 System.Collections.Concurrent 命名空间 - 其中有一个线程安全的队列实现,即 ConcurrentQueue - 尽管我怀疑你更需要 BlockingCollection
阻塞集合是一种线程安全的集合,用于生产者-消费者场景。在你的情况下,WCF 调用将充当添加到集合的生产者,而工作线程将充当从集合中获取排队任务的消费者。通过使用单个消费者(和集合),可以确保执行顺序。如果这不重要,那么您可以使用多个消费者线程。(还有 AddAnyTakeAny 静态重载,如果需要,可以使用多个集合(多个队列)。)
while(true) 方法相比的优点是避免了仅会消耗 CPU 循环的紧密循环。除了具有线程安全性外,这也解决了排队和取消排队线程之间同步的问题。 编辑
阻塞集合非常简单易用。请参见以下简单示例 - 添加任务将从你的 WCF 方法中调用以排队任务,而 StartConsumer 将在服务启动期间调用。
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

谢谢,能否请您解释一下...“while StartConsumer will be called during service start-up”是什么意思?我该如何调用StartConsumer函数?在哪里放置它? - SexyMF
@SexyMF,我假设您正在将WCF服务打包为Windows服务。基本上,您需要在启动时启动消费者线程,然后等待添加任务以便可以处理它们! - VinayC
那么你的意思是说 _tasks 应该是 public static 的吗?这样我就可以从 global asax 中访问它了? - SexyMF
@SexyMF - 是的 - 它将是一个静态成员(不需要将其公开 - 而是使诸如“AddTask”、“StartConsumer”之类的方法成为公共静态方法。 - VinayC
谢谢,你有Odesk账户吗? - SexyMF
显示剩余2条评论

0

我会使用事件来同步队列,而不是无限循环。每当进行WCF调用时,将元素添加到队列中并发送“AnElementHasBeenAddedEvent”事件。

执行排队任务的线程侦听该事件,并在接收到它时清空队列。

确保只有一个线程执行此任务!

相比while(true)概念的优势:您不需要一个不断循环的线程,从而消耗资源。您只需尽可能少地工作。


我同意这个观点。此外:使用队列的Synchronized方法,因为队列不是线程安全的:Queue.Synchronized(queue).Dequeue() - MatthiasG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接