为什么foreach与Parallel.ForEach之间存在这种差异

本文关键字:存在 之间 foreach Parallel ForEach 为什么 | 更新日期: 2023-09-27 18:36:09

谁能用简单的语言向我解释为什么我在使用 foreach 时得到一个大约 65 k 的文件,而在使用 Parallel.ForEach 时得到超过 3 GB 的文件?

foreach的代码:

// start node xml document
var logItems = new XElement("log", new XAttribute("start", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss")));
var products = new ProductLogic().SelectProducts();
var productGroupLogic = new ProductGroupLogic();
var productOptionLogic = new ProductOptionLogic();
// loop through all products
foreach (var product in products)
{
    // is in a specific group
    var id = Convert.ToInt32(product["ProductID"]);
    var isInGroup = productGroupLogic.GetProductGroups(new int[] { id }.ToList(), groupId).Count > 0;
    // get product stock per option
    var productSizes = productOptionLogic.GetProductStockByProductId(id).ToList();
    // any stock available
    var stock = productSizes.Sum(ps => ps.Stock);
    var hasStock = stock > 0;
    // get webpage for this product
    var productUrl = string.Format(url, id);
    var htmlPage = Html.Page.GetWebPage(productUrl);
    // check if there is anything to log
    var addToLog = false;
    XElement sizeElements = null;
    // if has no stock or in group
    if (!hasStock || isInGroupNew)
    {
        // page shows => not ok => LOG!
        if (!htmlPage.NotFound) addToLog = true;
    }
    // if page is ok
    if (htmlPage.IsOk)
    {
        sizeElements = GetSizeElements(htmlPage.Html, productSizes);
        addToLog = sizeElements != null;
    }
    if (addToLog) logItems.Add(CreateElement(productUrl, htmlPage, stock, isInGroup, sizeElements));
}
// save
var xDocument = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), new XElement("log", logItems));
xDocument.Save(fileName);

并行代码的使用是一个很小的变化,只是将foreach替换为Parallel.ForEach:

// loop through all products
Parallel.ForEach(products, product =>
{
    ... code ...
};

方法GetSizeElements和CreateElements都是静态的。

更新1我用锁使方法GetSizeElements和CreateElements成为线程安全的,也没有帮助。

更新2我得到解决问题的答案。这很好,很好。但是我想了解更多有关为什么此代码创建一个比foreach解决方案大得多的文件的信息。我正在尝试在使用线程时更了解代码的工作方式。这样我就能获得更多的洞察力,并学会避免陷阱。

为什么foreach与Parallel.ForEach之间存在这种差异

有一件事很突出:

if (addToLog) 
  logItems.Add(CreateElement(productUrl, htmlPage, stock, isInGroup, sizeElements));

logItems不是胎面安全的。这可能是你的核心问题,但还有很多其他的可能性。

你有输出文件,寻找差异。

尝试在 foreach 循环中定义以下参数。

var productGroupLogic = new ProductGroupLogic();
var productOptionLogic = new ProductOptionLogic();

我认为只有两个被并行 foreach 循环中的所有线程使用,并且结果不必要地成倍增加。