I’m writing a polling system against SQL Server. When tasks are retrieved, they are off-loaded to a new thread using Task.Factory.StartNew(). The whole thing is inside an endless loop and I want to allow only N concurrent tasks.
while(true)
{
// create connection
while(_concurrentTasks < _allowedTasks)
{
// get job info
if(!reader.HasRows) break; // no work to do.
while(reader.Read())
{
// fill JobInfo entity from reader
_taskCollection.Add(Task.Factory.StartNew(() => ProcessJob(jobInfo)));
_concurrentTasks++;
}
}
// could break for 1 of 2 reasons, threshold met or nothing to do
if((_concurrentTasks < _allowedTasks)
{
// sleep for a predetermined period of time
Thread.Sleep(60000);
}
else
{
// wait for one thread to complete and then get more jobs
Task.WaitAny(_taskCollection.ToArray);
}
}
I’m not sure which collection would be best to use in this situation or how to clean up the tasks that have been completed.
If I put the cleanup code in the task itself, I can use List<Task> along with the Task.CurrentId property to identify the item in the collection, but I don’t believe I can dispose of the Task object in the collection within the task itself; also note that the collection would have to be threadsafe.
If I put some kind of cleanup code outside the task (in the main thread), I wouldn’t need a threadsafe collection, but I have no idea when a task completes in the main thread.
So, which collection should I use to maintain a list/array of concurrent tasks so I can use WaitAny() and how can I clean up the list when one completes?
I’ve decided to use an array and loop through it when necessary: