c# - 多线程环境中的任务列表 - "enumeration operation may not execute"

标签 c# multithreading task-parallel-library

我有一个任务工厂,它启动许多任务,有时超过 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/

相关文章:

c# - .NET 任务/TPL 测试和模拟? (或者用法不正确?)

c# - 多级DI重构

c# - 创建数据上下文对象的更短方法?

c++ - (简单) boost 线程组问题

c# - 为什么 HTTP 请求永远不会返回异步等待?

c# - 等待来自多个对象的任务

c# - C# 中的 FbDataReader 到 ArrayList

c# - 休息服务用双引号弄乱字符串

multithreading - TOmniEventMonitor 可以在后台线程中使用吗?

java - java中如何将对象的方法和对象作为单独的线程调用?