我有一个任务工厂,它启动许多任务,有时超过 1000 个。我将每个任务添加到列表中,并在任务完成后将其删除。
var scan = Task.Factory.StartNew(() =>
{
return operation.Run();
}, token.Token
);
operations.Add(scan);
任务完成时:
var finishedTask = scan.ContinueWith(resultTask =>
OperationComplete(resultTask),
TaskContinuationOptions.OnlyOnRanToCompletion
);
public virtual void OperationComplete(Task task)
{
operations.Remove(task);
}
全部完成后:
Task.Factory.ContinueWhenAll(operations.ToArray(),
result =>
{
AllOperationsComplete();
}, TaskContinuationOptions.None);
然后,在我的应用程序中的某些点上,我想获取正在运行的任务的计数。 (这是我收到错误的地方:“集合已修改;枚举操作可能无法执行。”)
public int Count()
{
int running = operations.Count<Task>((x) => x.Status == TaskStatus.Running);
return running;
}
几个问题:
1) 我是否应该担心从列表中删除任务?该列表很可能有 1000 多个。
2) 使 Count() 安全的最佳方法是什么?如果我没记错的话,创建一个新列表并向其中添加 操作
仍然会枚举该集合。
最佳答案
您需要锁定以确保一次只有一个线程访问列表(无论是在删除期间还是计数期间),或者您应该使用并发集合。不要忘记Count(Func<T, bool>)
需要迭代集合才能执行计数 - 就像使用 foreach
循环...并且在迭代集合时(通常)无法修改集合。
我怀疑 ConcurrentBag
在这里是一个合适的选择 - 当您使用 TPL 时,大概您有可用的 .NET 4 并发集合...
关于c# - 多线程环境中的任务列表 - "enumeration operation may not execute",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11819167/