2

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

我有一个 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 循环时,它总是正确的。

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

4

2 回答 2

3

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

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

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

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

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

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

于 2013-12-16T17:43:43.450 回答
0
  1. ArrayList 不是线程安全的;在这里查看并发集合。

  2. isExistImage 线程安全吗?即您在更新任何成员变量之前是否锁定?

于 2013-12-16T14:09:27.007 回答