【问题标题】:C# - Queue Management that that always run and DequeingC# - 始终运行和出队的队列管理
【发布时间】:2012-03-26 09:00:35
【问题描述】:

我需要构建一个在 WCF 中侦听新任务的进程。 (异步) 每个任务(以某种方式)都会入队。

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

我想过:

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

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

谢谢

【问题讨论】:

    标签: c# queue


    【解决方案1】:

    看看System.Collections.Concurrent 命名空间 - 有线程安全的队列实现,即。 ConcurrentQueue - 不过,我怀疑BlockingCollection 会更好地满足您的需求。

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

    while(true) 方法相比的优势在于避免了只会消耗 CPU 周期的紧密循环。除了线程安全之外,这还可以解决排队和出队线程之间的同步问题。

    编辑

    Blocking Collection 使用起来非常简单。请参见下面的简单示例 - 将从您的 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,我假设您将 WCF 服务打包为 Windows 服务。本质上,您需要在启动时启动消费者线程,然后等待添加任务以便处理它们!
    • 那么你说 _tasks 应该是公共静态的?所以我无法从全局 asax 访问它?
    • @SexyMF - 是的 - 这将是一个静态成员(无需将其公开 - 而是将诸如 AddTaskStartConsumer 等方法公开静态。
    • 谢谢你,你真的帮了我,一个问题,当我调用时,我在线程窗口中没有看到一个新的线程行,这是为什么?这不是假设在单个线程中执行吗?
    【解决方案2】:

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

    执行队列任务的线程会监听该事件,每当它接收到该事件时,队列就会被清空。

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

    while(true) 概念的优势:您没有一个线程不断循环通过无限循环并因此吃掉资源。你只做需要的工作。

    【讨论】:

    • 我同意这一点。另外:使用队列的Synchronized方法作为队列不是线程安全的:Queue.Synchronized(queue).Dequeue()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多