首页 > 解决方案 > 处理对象以清除内存

问题描述

我有这个代码:

public static void GetAllProductsFromIndexes_AndPutInDB(List<IndexModel> indexes)
{
    BlockingCollection<IndexModel> inputQueue = CreateInputQueue(indexes);
    BlockingCollection<Product> productsQueue = new BlockingCollection<Product>(5000);

    var producers = Enumerable.Range(0, 50)
        .Select(_ => Task.Run(() =>
        {
            foreach (IndexModel index in inputQueue.GetConsumingEnumerable())
            {
                Product product = new Product();
                byte[] unconvertedByteArray;
                string xml;
                string url = @"https://data.Icecat.biz/export/freexml.int/en/";

                unconvertedByteArray = DownloadIcecatFile(index.IndexNumber.ToString() + ".xml", url);
                xml = Encoding.UTF8.GetString(unconvertedByteArray);
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(xml);

                GetProductDetails(product, xmlDoc, index);

                XmlNodeList nodeList = (xmlDoc.SelectNodes("ICECAT-interface/Product/ProductFeature"));
                product.FeaturesLink = GetProductFeatures(product, nodeList);

                nodeList = (xmlDoc.SelectNodes("ICECAT-interface/Product/ProductGallery/ProductPicture"));
                product.Images = GetProductImages(nodeList);
                productsQueue.Add(product);
            }

        })).ToArray();

    for (int i = 0; i < 10; i++)
    {
        Task.Run(() =>
        {
            using (var context = new ProductContext())
            {
                var batch = new List<Product>();
                foreach (Product readyProduct in productsQueue.GetConsumingEnumerable())
                {
                    AddProductToBatch(readyProduct, context, batch);
                    if (batch.Count >= 100)
                    {
                        context.Products.AddRange(batch);
                        context.SaveChanges();
                        foreach (var p in batch)
                        {
                            context.Entry(p).State = EntityState.Detached;
                        }
                        batch.Clear();
                    }
                }
                context.Products.AddRange(batch);
                context.SaveChanges();
                foreach (var p in batch)
                {
                    context.Entry(p).State = EntityState.Detached;
                }
            }

        });
    }
    Task.WaitAll(producers);
    productsQueue.CompleteAdding();
}

我正在尝试使用生产者消费者模式将 114000 种产品放入数据库。到目前为止,我已经设法在大约 1.5 小时内将大约 40000 种产品输入数据库。但随后程序停止,因为我的内存不足。我显然没有正确处理某些东西,在我使用完它之后,一旦产品被添加到 productsQueue 中,我就是不知道如何处理来自 inputQueue 的索引。

标签: c#

解决方案


推荐阅读