How to remove a task from the collection after completion

Let's say I have a collection System.Threading.Tasks.Task:

HashSet<Task> myTasks = new HashSet<Task>();

... and I periodically upload more to the collection, since 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 they Taskremain in a state TaskStatus.RanToCompletionafter completion, and not just disappear, they remain in the collection until they are explicitly deleted, and the collection will grow indefinitely. Taskmust be trimmed to prevent this.

One approach that I examined gives access to the collection Taskand deletes it at the very end. But I also look at architecture, where I will have to delete a task that my component has not created. My first thought is to attach a trigger or event to the 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();
}

... Task . , ? - :

+5
3

, : Task.ContinueWith ( ). , , .

, ConcurrentDictionary - . Keys , , .

+12

?

BlockingCollection Parallel.ForEach

var sources = new BlockingCollection<DataItem>();

Task.Factory.StartNew(() => {
    Parallel.ForEach(sources.GetConsumingPartitioner(),
                     item => Process(item));
});

, .

foreach (DataItem item in itemsToProcess)
    sources.Add(item);

sources.Count foreach (DataItem item in sources) . ( , )

+2

Use ContinueWith to set an action that removes a task from the set.

+1
source

All Articles