c# - 将 for 循环转换为 Task.Parallel.For

标签 c# parallel-processing task-parallel-library parallel.for

我有一个过程 bool IsExistImage(int i) 。该过程的任务是检测图像并返回 bool 值是否存在。

我有一个 100 多页的 PDF,我通过该方法将其拆分并仅发送文件名。文件名实际上是主 PDF 文件的页码。例如 1,2,3,...,125,..

检测到图像后,我的方法正确保存了页面列表。为此,我使用了这段代码:

ArrayList array1 = new ArrayList();
for(int i=1;i<pdf.length;i++)
{
   if(isExistImage(i))
   {
       array1.add(i);
   }
}

这个过程运行了超过1个小时(显​​然是isExistImage()方法的内部工作。)。我可以向您保证,在方法范围之外没有任何对象/变量是全局的。

因此,为了缩短时间,我使用了 Task.Parallel For 循环。这就是我所做的:

System.Threading.Tasks,Parallel.For(1,pdf.Length,i =>
{
    if(isExistImage(i))
        array1.Add(i);
}

但这不能正常工作。有时图像检测是正确的。但大多数时候它是错误的。当我使用非并行 for 循环时,它总是正确的。

我不明白这里有什么问题。我应该在这里申请什么。我还缺少什么技巧吗?

最佳答案

你的问题是ArrayList (以及大多数其他 .Net 集合)不是线程安全的。

有多种方法可以解决此问题,但我认为在这种情况下,最好的选择是使用 PLINQ:

List<int> pagesWithImages = ParallelEnumerable.Range(1, pdf.Length)
    .Where(i => isExistImage(i))
    .ToList();

这将使用多个线程来调用(奇怪的命名)isExistImage方法,这正是你想要的,然后返回 List<int>包含与条件匹配的索引。

返回的列表不会被排序。如果您需要,请添加 AsOrdered()之前Where() .

顺便说一句,你真的不应该使用 ArrayList 。如果您想要整数列表,请使用 List<int> .

关于c# - 将 for 循环转换为 Task.Parallel.For,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20612664/

相关文章:

javascript - JavaScript/NodeJS 真的是并行的吗?

C#转安卓聊天客户端

c# - 如何在 c# 中禁用磁盘缓存使用 FILE_FLAG_NO_BUFFERING 调用 win32 CreateFile api

c# - 无法解析作用域服务 DbContextOptions

c++ - 在 Linux 中调试期间是否可以停止单个线程?

java - 如何在构造函数中同时解析 URL?

c# - Entity Framework ——如何在缩写的 EF linq 中实现这个 SQL

c# - 这是 Partitioner.Create(int fromInclusive, int toExclusive) 中的错误吗?

c# - 从异步 ApiController 返回即时响应

c# - 为什么这个对象为空?