I am running my tasks for maxdegreeofparallelism using parallel.foreach and if there's a task taking too long time to complete then all have to wait for next iteration process.
Now, the scenario is, I have mutiple file orders processing performed by my windows service and on first phase I fetch my file orders from db, then do some manipulations over those records and then pass that list of file orders with maxdegreeofparallelism to my parallel for each tasking.
There are few files in my file orders records those have many documents like 100 or 200 and into those documents have many pages as well. So, performing tasking such that taking too much time because If an order has processed for short size file having less documents or pages will wait for others to be finished dealing with larges documents or pages.
Now I want those particular free / completed task running in parallel should get new db record for next file order and start processing that one in parallel.
Two exceptions are, the next fetched file orders shouldn't be the ones those are already processed by another tasks in parallel and number of parallel tasks processing should also not exceeded by given max degree of parallelism / maximum scheduled tasks for this service to process all file orders.
Please suggest a better solution for this.
What I have tried:
public static Task StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, CancellationToken cancellationToken = new CancellationToken())
{
return StartAndWaitAllThrottled(tasksToRun, maxTasksToRunInParallel, -1, cancellationToken);
}
public static Task StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, int timeoutInMilliseconds, CancellationToken cancellationToken = new CancellationToken())
{
var tasks = tasksToRun.ToList();
using (var throttler = new SemaphoreSlim(1,maxTasksToRunInParallel))
{
var postTaskTasks = new List<Task>();
tasks.ForEach(t => postTaskTasks.Add(t.ContinueWith(tsk => throttler.Release())));
foreach (var task in tasks)
{
throttler.Wait(timeoutInMilliseconds, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
task.Start();
}
Task.WaitAll(postTaskTasks.ToArray(), cancellationToken);
}
}