如何在完成后从集合中删除任务

Cal*_*her 6 c# .net-4.0 task-parallel-library

假设我有一个集合System.Threading.Tasks.Task:

HashSet<Task> myTasks = new HashSet<Task>();
Run Code Online (Sandbox Code Playgroud)

...我定期向集合中提供更多内容,因为我有更多需要处理的数据:

foreach (DataItem item in itemsToProcess)
    myTasks.Add(
        Task.Factory.StartNew(
            () => Process(item),
            cancellationToken,
            TaskCreationOptions.LongRunning,
            TaskScheduler.Default));    
Run Code Online (Sandbox Code Playgroud)

由于Tasks TaskStatus.RanToCompletion在完成后仍保持状态而不是仅仅消失,因此它们将保留在集合中,直到明确删除并且集合将无限增长.该Task的需要进行修剪,以防止这一点.

我看过的一种方法是提供对Task集合的访问,并在最后将其删除.但我也在看一个架构,我必须删除我的组件尚未创建的任务.我的第一个想法是附加一个触发器或事件来完成每个任务,如下所示:

foreach (Task task in createdSomewhereElse)
{
    lock (myTasks) myTasks.Add(task);
    task.WhenTaskIsCompleted += 
        (o, ea) => { lock(myTasks) myTasks.Remove(task); };
    task.Start();
}
Run Code Online (Sandbox Code Playgroud)

......但Task没有这样的事件.有没有什么好方法可以完成我正在寻找的东西?像这样的东西:

Jon*_*eet 15

您当然可以在任务完成时附加触发器:( Task.ContinueWith及其通用等效项).这对你来说可能已经足够了.

可能还希望将其ConcurrentDictionary用作一种穷人的并发集 - 这样您在访问集合时就不必锁定.只需Keys在迭代时使用该属性,并使用您喜欢的任何值作为值.

  • 那似乎正是我想要做的。:)因此,用`task.ContinueWith((t)=&gt; {lock(myTasks)myTasks.Remove(t);});替换`+ =`语句是正确的吗?另外,对@LukeH的评论+1;我在系统库中没有看到其中之一。 (2认同)