Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Element order in BlockingCollection<>

I have a Download Queue implemented with BlockingCollection<>. Now I want to prioritize some Download once in a while. I thought it might be great to move some elements 'up' the Collection, like in a list, but there is no method like Remove()/AddFirst() or Move().

What's the preferred way of arranging items in a BlockingCollection<> ?

like image 989
Matthieu Petite Avatar asked Sep 21 '11 15:09

Matthieu Petite


People also ask

Is Blockcollection a FIFO?

That being said, BlockingCollection<T> works upon any IProducerConsumerCollection<T> (specified in the constructor). If you don't provide one in the constructor, internally, it will use a ConcurrentQueue<T> . This causes it to be FIFO, since it will actually be (internally) a queue.

What is BlockingCollection in c#?

BlockingCollection<T> is a thread-safe collection class that provides the following features: An implementation of the Producer-Consumer pattern. Concurrent adding and taking of items from multiple threads. Optional maximum capacity. Insertion and removal operations that block when collection is empty or full.


1 Answers

Reed is correct in telling you that you need to implement the IProducerConsumerCollection<T>. However, there is a class that can help you. It's not built in, but it's featured on MSDN. Just pass this ConcurrentPriorityQueue to your BlockingCollection.

This is how I used it:

private readonly BlockingCollection<KeyValuePair<int, ICommand>> _commands 
    = new BlockingCollection<KeyValuePair<int, ICommand>>(
        new ConcurrentPriorityQueue<int, ICommand>());

The ICommand is an interface in my project.

Now this allows you to add items like this:

_actions.Add(new KeyValuePair<int, ICommand>(1, command1));
_actions.Add(new KeyValuePair<int, ICommand>(2, command2));
_actions.Add(new KeyValuePair<int, ICommand>(1, command3));

Items with a lower integer value as priority will be executed first. In the above example:

command1
command3
command2

When looping over your BlockingCollection, you will no longer get the single elements (ICommand in my case), but a KeyValuePair. This might require some code changes of course. A nice thing is that you have its original priority:

foreach (var command in _queue) 
{
    var priority = command.Key;
    var actualCommand = command.Value;
}
like image 74
Peter Avatar answered Oct 18 '22 17:10

Peter