HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Collection to hold maximum number of running Tasks

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
numbermaximumcollectionholdrunningtasks

Problem

I need a collection/bag (something) that will hold some maximum number of running Task objects. Adding a new running Task to the collection should block the calling thread (there are many threads trying to add a task so it should be thread safe) until there is an available slot for the new Task to be added if the maximum number of running tasks is reached. This is what I have so far and it is working fine.

Can you find any problems with this code? Or is there some built-in class that can handle this kind of task?

public class ConcurrentTaskLimiter
{
    public int MaxWorkingTasks { get; }
    private readonly Task[] _tasks;
    private readonly bool[] _finished;

    public ConcurrentTaskLimiter(int maxWorkingTasks)
    {
        MaxWorkingTasks = maxWorkingTasks;
        if ((1 = 1");
        _tasks = new Task[maxWorkingTasks];
        _finished = new bool[maxWorkingTasks];

        for (int i = 0; i < MaxWorkingTasks; i++)
        {
            _tasks[i] = Task.FromResult(0); // use this as finished tasks
            _finished[i] = true;
        }
    }

    public void BlockAdd(Task t)
    {
        if (t == null)
            throw new ArgumentNullException(nameof(t));

        if (t.Status == TaskStatus.Canceled
            || t.Status == TaskStatus.Faulted
            || t.Status == TaskStatus.RanToCompletion)
            return;

        lock (this)
        {
            int i;
            while (true)
            {
                for (i = 0; i < MaxWorkingTasks; i++)
                {
                    if (_finished[i])
                    {
                        _tasks[i] = t;
                        _finished[i] = false;
                        return;
                    }
                }
                i = Task.WaitAny(_tasks);
                _finished[i] = true;
            }
        }
    }
}

Solution

What you have described here is a Producer- Consumer relationship. .Net has a BlockingCollection that performs exactly what you are trying to create here

public BlockingCollection(
    IProducerConsumerCollection collection,
    int boundedCapacity
)



You could use a ConcurrentBag as the underlying store or any ConcurrentCollection of your choice and the boundedCapacitycan be the maximum number of Tasks that can be added to the collection. An example usage is

BlockingCollection messages = new BlockingCollection(new ConcurrentBag(), 10);

Code Snippets

public BlockingCollection(
    IProducerConsumerCollection<T> collection,
    int boundedCapacity
)
BlockingCollection<int> messages = new BlockingCollection<int>(new ConcurrentBag<int>(), 10);

Context

StackExchange Code Review Q#150825, answer score: 3

Revisions (0)

No revisions yet.