You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C# Task多线程处理大PDF文件文本提取异常问题

问题分析与解决方案

核心问题排查

1. 闭包变量捕获陷阱

循环中直接在Task.Run里引用startpage变量,由于闭包捕获的是变量引用而非当前值,所有任务最终可能拿到的都是循环结束时的startpage值,导致大量任务重复处理同一页面范围,或跳过大量页面。

2. 页面范围计算错误

循环步长startpage = startpage + num + 1会导致页面区间遗漏:

  • 若总页数不是num+1的整数倍,末尾的若干页面会被跳过;
  • 当startpage+num超过总页数时,ProcessSinglePDF会处理不存在的页面,引发隐性错误。

3. PdfReader线程不安全

iTextSharp的PdfReader实例不支持多线程并发访问,多个任务共用同一个reader会导致内部状态混乱,出现读取失败、数据丢失甚至任务异常静默终止。

4. 异常未处理

未捕获任务执行中的异常,若某个任务因页面不存在、数据库错误等抛出异常,await时未处理会导致程序看似正常完成,但实际任务已失败。


修正后的代码

var processTask = new List<Task>();
var pdfDir = Path.Combine(sourcePath, "PDFs");
Directory.CreateDirectory(pdfDir); // 确保输出目录存在

int totalPages = reader.NumberOfPages;
for (int startpage = 1; startpage <= totalPages; startpage += num)
{
    // 复制循环变量到局部变量,规避闭包陷阱
    int currentStart = startpage;
    // 计算当前区间的结束页,避免超过总页数
    int currentEnd = Math.Min(currentStart + num - 1, totalPages);
    
    processTask.Add(Task.Run(async () => 
    {
        // 每个任务创建独立的PdfReader实例,保证线程安全
        using (var taskReader = new PdfReader(fileInfo.FullName))
        {
            var outputPath = Path.Combine(pdfDir, $"{currentStart}.pdf");
            await ProccesSinglePDF(
                taskReader, 
                outputPath,
                currentStart,
                currentEnd,
                new FileInfo(outputPath), 
                searchText);
        }
    }));
}

// 等待所有任务完成,并统一捕获异常
try
{
    await Task.WhenAll(processTask);
}
catch (AggregateException ex)
{
    foreach (var innerEx in ex.InnerExceptions)
    {
        Console.WriteLine($"任务执行失败: {innerEx.Message}");
    }
}

额外优化建议

  • 数据库并发控制:多个任务写数据库时,依赖数据库连接池(默认开启)即可,若存在冲突可考虑批量写入或事务控制;
  • 并发数限制:用SemaphoreSlim限制并发任务数,防止CPU/内存过载:
    var semaphore = new SemaphoreSlim(Environment.ProcessorCount * 2); // 并发数设为CPU核心数的2倍
    // 在任务内部先获取信号量
    await semaphore.WaitAsync();
    try
    {
        // 任务逻辑
    }
    finally
    {
        semaphore.Release();
    }
    
  • 日志记录:在ProcessSinglePDF中添加页面范围、处理结果的日志,方便排查问题。

内容的提问来源于stack exchange,提问作者Elmer A. Chacon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 03:15:36