为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Parallel.ForEach 与 TPL.Dataflow 或其他将 OCR 应用于大量

使用 Parallel.ForEach 与 TPL.Dataflow 或其他将 OCR 应用于大量

C#
月关宝盒 2022-12-31 13:12:01
我正在创建一个应用程序来批处理 OCR 图像,现在我正在使用异步 Parallel.ForEach 方法来遍历包含文件名和 OCR 文本字段的对象列表(打印输出)。我想知道这是否是解决此问题的最佳方法。我读过有关 TPL.Dataflow 的文章,虽然它看起来有点矫枉过正,但我想知道使用更复杂的方法是否更好,因为我可能会同时处理数百个文件,而且我不确定是否创建了数百个任务是很好的做法。另外,我读过在 Parallel.ForEach 中使用 Interlocked.Increment 是不好的做法,我应该将其转换为 Parallel.For 吗?下面是我当前的实现:private async void BatchOCR_Click(object sender, EventArgs e) {   //some UI stuff   source = new CancellationTokenSource();   progressBar.Value = 0;   int counter = 0;   IProgress<int> progress = new Progress<int>(i => { progressBar.Value = (int)Math.Round((float)(i)*100 / fileList.Items.Count, 0); });   await Task.Run(() => RunBatchOCR(ListOfPrintouts,progress,counter), source.Token);   //some UI stuff}private async Task RunBatchOCR(List<Printout> printouts,IProgress<int> progress, int counter) {   progress.Report(0);   Parallel.ForEach(printouts, (printout,state) =>      {         try         {            source.Token.ThrowIfCancellationRequested();         }         catch         {            Console.WriteLine("Task was cancelled");            cancelButton.Enabled = false;            state.Break();          }          finally          {             Interlocked.Increment(ref counter);          }          printout.OcrHelper.runOCR(); //loads bitmap and extracts text          progress.Report(counter);          Console.WriteLine(counter.ToString());    });}
查看完整描述

1 回答

?
胡子哥哥

TA贡献1825条经验 获得超6个赞

我不确定创建数百个任务是否是一个好习惯


没关系。Parallel使用智能分区。


关于代码的其余部分,Interlocked可以用作计数器,但您不想在没有互锁障碍的情况下访问相同的变量。该CancellationToken代码需要简化:


private async Task RunBatchOCR(List<Printout> printouts, IProgress<int> progress)

{

  int counter = 0;

  progress?.Report(0);

  try

  {

    Parallel.ForEach(printouts, new ParallelOptions { CancellationToken = source.Token }, printout =>

    {

      printout.OcrHelper.runOCR(); //loads bitmap and extracts text

      var update = Interlocked.Increment(ref counter);

      progress?.Report(update);

      Console.WriteLine(update.ToString());

    });

  }

  catch (OperationCanceledException)

  {

    Console.WriteLine("Task was cancelled");

    cancelButton.Enabled = false;

  }

}


查看完整回答
反对 回复 2022-12-31
  • 1 回答
  • 0 关注
  • 85 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信