简体   繁体   English

使用阻塞收集和任务的经典生产者消费者模式 .net 4 TPL

[英]classic producer consumer pattern using blockingcollection and tasks .net 4 TPL

Please see below pseudo code请看下面的伪代码

//Single or multiple Producers produce using below method
    void Produce(object itemToQueue)
    {
        concurrentQueue.enqueue(itemToQueue);
        consumerSignal.set;
    }

    //somewhere else we have started a consumer like this
    //we have only one consumer
    void StartConsumer()
    {
        while (!concurrentQueue.IsEmpty())
        {
            if (concurrentQueue.TrydeQueue(out item))
            {
                //long running processing of item
            }
        }
        consumerSignal.WaitOne();
    }

How do I port this pattern I have used since time immemorial to use taskfactory created tasks and the new signalling features of net 4. In other words if someone were to write this pattern using net 4 how would it look like?我如何移植自远古以来就使用的这种模式,以使用 taskfactory 创建的任务和 net 4 的新信号功能。换句话说,如果有人要使用 net 4 编写这种模式,它会是什么样子? Pseudo code is fine.伪代码很好。 Iam already using .net 4 concurrentQueue as you can see.如您所见,我已经在使用 .net 4 concurrentQueue。 How do I use a task and possibly use some newer signalling mechanism if possible.如果可能,我如何使用任务并可能使用一些更新的信号机制。 thanks谢谢

Solution to my problem below thanks to Jon/Dan.感谢 Jon/Dan 解决了我的问题。 Sweet.甜的。 No manual signalling or while(true) or while(itemstoProcess) type loops like the old days没有像过去那样的手动信号或 while(true) 或 while(itemstoProcess) 类型循环

//Single or multiple Producers produce using below method
 void Produce(object itemToQueue)
 {
     blockingCollection.add(item);
 }

 //somewhere else we have started a consumer like this
 //this supports multiple consumers !
 task(StartConsuming()).Start; 

 void StartConsuming()
 {
     foreach (object item in blockingCollection.GetConsumingEnumerable())
     {
                //long running processing of item
     }
 }

cancellations are handled using cancel tokens

You would use BlockingCollection<T> .您将使用BlockingCollection<T> There's an example in the documentation.文档中有一个示例。

That class is specifically designed to make this trivial. class 专门设计用于使这变得微不足道。

Your second block of code looks better.您的第二个代码块看起来更好。 But, starting a Task and then immediately waiting on it is pointless.但是,启动一个Task然后立即等待它是没有意义的。 Just call Take and then process the item that is returned directly on the consuming thread.只需调用Take然后处理直接在消费线程上返回的项目。 That is how the producer-consumer pattern is meant to be done.这就是生产者-消费者模式的意义所在。 If you think the processing of work items is intensive enough to warrant more consumers then by all means start more consumers.如果您认为工作项的处理足够密集以保证更多的消费者,那么一定要启动更多的消费者。 BlockingCollection is safe multiple producers and multiple consumers. BlockingCollection是安全的多个生产者多个消费者。

public class YourCode
{
  private BlockingCollection<object> queue = new BlockingCollection<object>();

  public YourCode()
  {
    var thread = new Thread(StartConsuming);
    thread.IsBackground = true;
    thread.Start();
  }

  public void Produce(object item)
  {
    queue.Add(item);
  }

  private void StartConsuming()
  {
    while (true)
    {
      object item = queue.Take();
      // Add your code to process the item here.
      // Do not start another task or thread. 
    }
  }
}

I've used a pattern before that creates a sort of 'on-demand' queue consumer (based on consuming from a ConcurrentQueue):我之前使用过一种模式,它创建了一种“按需”队列消费者(基于从 ConcurrentQueue 消费):

        private void FireAndForget(Action fire)
        {
            _firedEvents.Enqueue(fire);
            lock (_taskLock)
            {
                if (_launcherTask == null)
                {
                    _launcherTask = new Task(LaunchEvents);
                    _launcherTask.ContinueWith(EventsComplete);
                    _launcherTask.Start();
                }
            }
        }

        private void LaunchEvents()
        {
            Action nextEvent;

            while (_firedEvents.TryDequeue(out nextEvent))
            {
                if (_synchronized)
                {
                    var syncEvent = nextEvent;
                    _mediator._syncContext.Send(state => syncEvent(), null);
                }
                else
                {
                    nextEvent();                        
                }

                lock (_taskLock)
                {
                    if (_firedEvents.Count == 0)
                    {
                        _launcherTask = null;
                        break;
                    }
                }
            }
        }

        private void EventsComplete(Task task)
        {
            if (task.IsFaulted && task.Exception != null)
            {
                 // Do something with task Exception here
            }
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用TPL的生产者使用者模型,.net 4.0中的任务 - Producer Consumer model using TPL, Tasks in .net 4.0 如何使用 BlockingCollection 通知生产者-消费者模式中的失败? - How to notify failure in producer-consumer pattern using BlockingCollection? 使用 BlockingCollection 通过生产者-消费者模式保存图像 - Saving images via producer-consumer pattern using BlockingCollection 如何使用C#TPL告诉生产者不要等待生产者-消费者模式 - How to tell producer to not wait in producer-consumer pattern using C# TPL 带有BlockingCollection的消费者/生产者看起来很慢 - Consumer/Producer with BlockingCollection appears slow 生产者/消费者,BlockingCollection和等待更改 - Producer/Consumer, BlockingCollection, and waiting for changes WPF,TPL,生产者/消费者模式 - 错误的线程错误 - WPF, TPL, Producer/Consumer Pattern - Wrong Thread Error 使用列表的消费者/生产者模式 - Consumer/producer pattern using a List 使用TPL实现经典异步模式 - Implement Classic Async Pattern using TPL 当生产者也是消费者时,如何在生产者/消费者模式中使用阻塞收集 - 我该如何结束? - How do I use a blockingcollection in the Producer/Consumer pattern when the producers are also the consumers - How do I end?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM