Let’s say I have a collection of System.Threading.Tasks.Task:
HashSet<Task> myTasks = new HashSet<Task>();
…and I periodically feed more into the collection as I have more data that needs to be processed:
foreach (DataItem item in itemsToProcess)
myTasks.Add(
Task.Factory.StartNew(
() => Process(item),
cancellationToken,
TaskCreationOptions.LongRunning,
TaskScheduler.Default));
Since Tasks remain in TaskStatus.RanToCompletion status after finishing instead of just disappearing, they would remain in the collection until explicitly removed and the collection would grow indefinitely. The Tasks need to be pruned to prevent this.
One approach I have looked at is giving the Task access to the collection and having it remove itself at the very end. But I am also looking at an architecture where I would have to remove a Task that my component has not created. My first thought is to attach a trigger or event to completion of each Task, something like this:
foreach (Task task in createdSomewhereElse)
{
lock (myTasks) myTasks.Add(task);
task.WhenTaskIsCompleted +=
(o, ea) => { lock(myTasks) myTasks.Remove(task); };
task.Start();
}
…but Task has no such event. Is there any good way to accomplish what I’m looking for? Something like this:
You certainly can attach a trigger for when a task is completed:
Task.ContinueWith(and its generic equivalent). That would probably be good enough for you.You may also wish to use
ConcurrentDictionaryas a sort of poor-man’s concurrent set – that way you wouldn’t have to lock when accessing the collection. Just use theKeysproperty when iterating, and use anything you like as the value.