2

我想将 PDF 转换为图像。我正在使用 Leadtools 并为了提高速度,我以以下方式使用多线程。

string multiPagePDF = @"Manual.pdf";
string destFileName = @"output\Manual";
Task.Factory.StartNew(() =>
{
    using (RasterCodecs codecs = new RasterCodecs())
    {
        CodecsImageInfo info = codecs.GetInformation(multiPagePDF, true);
        ParallelOptions po = new ParallelOptions();
        po.MaxDegreeOfParallelism = 5;
        Parallel.For(1, multiPagePDF.TotalPages+1, po, i =>
        {
            RasterImage image = codecs.Load(multiPagePDF, i);
            codecs.Save(image, destFileName + i + ".png", RasterImageFormat.Png, 0);
         });  
    }       
});

这是一种线程安全的方式吗?它会导致意外的输出吗?我尝试了几次,并且在某些情况下,特定页面在输出图像中出现了两次。

解决方案

根据 Leadtools 在线聊天支持(顺便说一句非常有帮助),Rastercodecs.load 不是线程安全的,上面的代码会导致意外输出(在我的例子中,第 1 页在输出图像集中出现了两次)。解决方案是在 Parallel.For 中定义编解码器变量,以便每次迭代单独访问其自己的 RasterCodecs。

4

1 回答 1

3

Amyn,正如您所发现的,在这种情况下使用 RasterCodecs 对象的正确方法是:

Task.Factory.StartNew(() =>
{
   using (RasterCodecs codecs = new RasterCodecs())
   {
      CodecsImageInfo info = codecs.GetInformation(multiPagePDF, true);
      ParallelOptions po = new ParallelOptions();
      po.MaxDegreeOfParallelism = 5;
      Parallel.For(1, info.TotalPages + 1, po, i =>
      {
         using(RasterCodecs codecs2 = new RasterCodecs()) {
           RasterImage image = codecs2.Load(multiPagePDF, i);
           codecs2.Save(image, destFileName + i + ".png", RasterImageFormat.Png, 0);
         }
      });
   }
});

这为您在多核处理器上运行时提供了相同的速度优势,而不会导致并发线程之间发生任何冲突。

LEADTOOLS RasterCodecs.Load() 和 RasterCodecs.Save() 方法是线程安全的。创建 RasterCodecs 类的多个实例背后的原因是,该类内部使用的结构包含许多不同的文件加载和保存选项。跨多个线程使用这些结构(更改这些选项的位置)可能会导致不可预知的结果。加载选项结构中的一个这样的属性是页码。因此,建议使用此类的单独实例。

于 2014-09-19T20:20:35.420 回答