我需要构建一个在WCF中侦听新任务的进程。 (异步) 每个任务都得到入队(不知何故)。
循环队列并将其出列的最佳(逻辑和性能)方法是什么。
我想到了:
while(true){
queue.Dequeue();
}
我认为有更好的方法可以做到这一点。
由于
答案 0 :(得分:7)
查看System.Collections.Concurrent命名空间 - 有线程安全队列实现即。 ConcurrentQueue - 尽管如此,我怀疑BlockingCollection可以更好地满足您的需求。
阻塞集合本质上是一个对生产者 - 消费者场景有用的线程安全集合。在您的情况下,WCF调用将充当将添加到集合的生成器,而工作线程将充当将基本上从集合中排队的任务的消费者。通过使用单个使用者(和集合),您可以确保执行顺序。如果这不重要,那么您可以使用多个消费者线程。 (还有AddAny
和TakeAny
静态重载,如果需要,可以使用多个集合(多个队列)。)
优于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)概念的优点:您没有一个不断循环遍历无限循环并因此占用资源的线程。你只需要做很多工作。