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 はどちらも静的です。
update1 メソッド GetSizeElements および CreateElements をロック付きでスレッドセーフにしましたが、これも役に立ちません。
update2 問題を解決するための回答が得られました。いいですよね。しかし、このコードが foreach ソリューションよりもはるかに大きなファイルを作成する理由について、さらに洞察を得たいと思います。スレッドを使用するときにコードがどのように機能するかについて、もう少し理解を深めようとしています。そうすれば、より多くの洞察が得られ、落とし穴を回避する方法を学ぶことができます。