[ACCEPTED]-classic producer consumer pattern using blockingcollection and tasks .net 4 TPL-pfx

Accepted answer
Score: 25

You would use BlockingCollection<T>. There's an example in the 2 documentation.

That class is specifically 1 designed to make this trivial.

Score: 11

Your second block of code looks better. But, starting 9 a Task and then immediately waiting on it is 8 pointless. Just call Take and then process the 7 item that is returned directly on the consuming 6 thread. That is how the producer-consumer 5 pattern is meant to be done. If you think 4 the processing of work items is intensive 3 enough to warrant more consumers then by 2 all means start more consumers. BlockingCollection is safe 1 multiple producers and multiple consumers.

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. 
    }
  }
}
Score: 1

I've used a pattern before that creates 2 a sort of 'on-demand' queue consumer (based 1 on consuming from a 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
            }
        }

More Related questions