I am trying to create a single consumer and multiple producers pattern. The producers will add tasks to the BlockingCollection and Consumer will run the tasks. I want to know if there is a way to know if the execution of all the tasks spawned by consumer is complete.
public TaskQueue(IProducerConsumerCollection<Task> workTaskCollection)
{
_workTaskQueue = new BlockingCollection<Task>(workTaskCollection);
}
public void EnqueueTask(Action action, CancellationToken cancelToken = default(CancellationToken))
{
var task = new Task(action, cancelToken);
if (_workTaskQueue.TryAdd(task))
{
TaskHandler?.Invoke
(new TaskProcessingArguments
{
ISTaskAdded = true,
Message = "Task Added to Queue",
PendingTaskCount = _workTaskQueue.Count,
});
}
else
{
TaskHandler?.Invoke
(new TaskProcessingArguments
{
ISTaskAdded = false,
Message = "Timedout while adding Task to Queue",
PendingTaskCount = _workTaskQueue.Count,
});
}
}
public void DequeueTask()
{
foreach (var task in _workTaskQueue.GetConsumingEnumerable())
try
{
if (!(task.IsCanceled) && task.Status == TaskStatus.Created)
{
task.Start();
}
}
catch (Exception ex)
{
}
}
public static void Run()
{
Task.Factory.StartNew(() =>
{
taskQueue.DequeueTask();
}, TaskCreationOptions.LongRunning);
}
Instead of providing 'EnqueueTask' with an Action (and creating the Task in the method), you could create the Task in the producer itself, and passing this to the 'EnqueueTask' method. In that way each producer could maintain a List of Tasks it has submitted, intermittently query the status for each of those and remove the ones that have finished.
This has the added advantage that the producer could cancel tasks it has submitted (even before they are launched) or detect tasks that are aborted due to exceptions.