【问题标题】:Parallel for each inconsistent results平行于每个不一致的结果
【发布时间】:2026-01-27 11:30:01
【问题描述】:

我确保我在并行循环中有并发收集。我期望在循环结束时有 35 个唯一的文件路径。我看到重复文件路径的结果不一致。我在这里错过了什么?

ConcurrentBag<string> generatedPdfFilePaths = new 
    ConcurrentBag<string>();                   
string generatedPdfPath = string.Empty;   
Parallel.ForEach(docxPaths, (docxpath) =>                    
{
    generatedPdfPath = docxpath.Replace(".docx", ".pdf");
    if (ConvertDocxToPdf(docxpath, generatedPdfPath))
    { 
        generatedPdfFilePaths.Add(generatedPdfPath); 
    }                    
});

// do stuff with generatedPdfFilePaths collection here
public bool ConvertDocxToPdf(string docxFilePath, string pdfFilePath)
{               
    try
    {
        Aspose.Words.Document docx = new
            Aspose.Words.Document(docxFilePath);
        docx.FontSettings = fontsetting;
        docx.Save(pdfFilePath);                   
        return true;
    }
    catch (Exception ex)
    {
        //do stuff
    }                
}

【问题讨论】:

  • string generatedPdfPath = string.Empty; 移动到Parallel.ForEach 循环体中。现在你无缘无故地从多个线程修改它。
  • 结果有什么不一致?
  • @InBetween 道歉 - 我通过在线美化器运行代码,不喜欢结果,所以在 Linqpad 中重新格式化 - 当我将其粘贴到 Linqpad 时,我的剪贴板上一定有美化版本- 过失!

标签: c# parallel-processing task-parallel-library parallel.foreach


【解决方案1】:

generatedPdfPathvariable 必须在并行循环内。否则,所有线程(并行循环)都可以访问它。在循环内部,每个线程都会修改它,当线程尝试使用它时,“可能”generatedPdfPath 值会被另一个线程更改。这种情况导致比赛条件。因此,每次执行都会给出不同的结果。

如果将这行string generatedPdfPath = string.Empty; 移动到循环中,问题必须解决。

ConcurrentBag<string> generatedPdfFilePaths = new ConcurrentBag<string>();                   

Parallel.ForEach(docxPaths, (docxpath) =>                    
{
    string generatedPdfPath = string.Empty;   
    generatedPdfPath = docxpath.Replace(".docx", ".pdf");
    if (ConvertDocxToPdf(docxpath, generatedPdfPath))
    { 
        generatedPdfFilePaths.Add(generatedPdfPath); 
    }                    
});

【讨论】:

    最近更新 更多