Oscar Calderon
Oscar Calderon

Reputation: 989

.NET TPL Start a task after one ends indefinitely

I have an application which process images extracted from database. I need to process various images in parallel, and because of that i'm using .NET TPL with Tasks.

My application is a Winforms app in C#. I just have the option to choose how many processes will start and a Start button. The way that i'm doing right now is this:

private Action getBusinessAction(int numProcess) {
    return () =>
    {
        try {
            while (true) {
                (new BusinessClass()).doSomeProcess(numProcess);
                tokenCancelacion.ThrowIfCancellationRequested();
            }
        }
        catch (OperationCanceledException ex) {
            Console.WriteLine("Cancelled process");
        }
    };
}

...

for (int cnt = 0; cnt < NUM_OF_MAX_PROCESS; cnt++) {
    Task.Factory.StartNew(getBusinessAction(cnt + 1), tokenCancelacion);
}

In this case, if i choose 8 as the number of processes, it starts 8 tasks which are running until application is closed. But i think that a better approach will be to start a number of tasks which calls doSomeProcess method, and then finish. But when a task finishes, i would like to start the same task or start a new instance of the task that does the same, in order to having always that number of processes running in parallel. Is there a way in TPL to achieve this?

Upvotes: 0

Views: 327

Answers (1)

i3arnon
i3arnon

Reputation: 116568

This sounds like a good fit for TPL Dataflow's ActionBlock. You create a single block at the start. Set how many items it should process concurrently (i.e. 8) and post the items into it:

var block = new ActionBlock<Image>(
    image => ProcessImage(image), 
    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 8});

foreach (var image in GetImages())
{
    block.Post(image);
}

This will take care of creating up to 8 tasks when needed and when they aren't anymore the number would go down.

When you are done you should signal the block for completion and wait for it to complete:

block.Complete();
await block.Completion;

Upvotes: 2

Related Questions