C#代码运行太慢。需要多线程

时间:2018-07-12 12:39:38

标签: c# multithreading

我发现很难使以下代码(使用Pastel Accounting SDK)执行得更快。目前需要几个小时才能更新:(

一些背景信息: 该代码从本地数据库中选择记录,然后在同一服务器上更新3个独立的数据库。在更新其他3个数据库时,它将在一次更新中完成。

更新所有3个数据库中的记录后,它们将使用新的数据副本更新本地数据库。

基本上是在更新价格,并保存旧价格。

我尝试实现多线程,但无法使其起作用:(

这是我的代码:

Amazon web service

我已经编辑了代码以添加多线程。但是该过程似乎根本没有运行。

public string ExportPrices(bool _restorePrices = false)
        {
            System.IO.File.AppendAllText(System.Web.HttpContext.Current.Server.MapPath("~/Logs/PriceUpdateErrorList.txt"), "Error Messages" + Environment.NewLine);

            var db = new UniStockContext();
            //fetch all databases to export to
            IList<AccDatabase> accDBCol = db.AccDatabases.Where(x => (x.Active == true) && (x.Deleted == false)).ToList();
            //fetch all inventory list
            IList<Domain.Tables.Inventory> inventoryDBCol = db.Inventories.Where(x => (x.Active == true) && (x.Deleted == false)).ToList();

            if (inventoryDBCol.Count > 0)
            {
                //string xmlResult = "<InventoryExportResponse>";
                //loop through databases and export
                foreach (AccDatabase accDB in accDBCol)
                {
                    //check database type and call appropriate accounting system method
                    if ((accDB.Type == AccDatabaseType.SageEvolution) && string.IsNullOrEmpty(accDB.EvolutionCommon))
                    {
                        //////////////////////////////////////////
                        //////////////Sage Evolution//////////////
                        //////////////////////////////////////////
                        foreach (AccDatabase accDB2 in accDBCol)
                        {
                            if ((accDB2.Type == AccDatabaseType.SageEvolution) && !string.IsNullOrEmpty(accDB2.EvolutionCommon))
                            {
                                //pass db and common db to export method for Sage Evolution
                                try
                                {
                                    if (!string.IsNullOrEmpty(accDB.DBName))
                                    {
                                        inventoryDBCol = _sageInventory.ExportPrices(accDB, accDB2, inventoryDBCol, restorPrices: false);//this call updates 13000 records
                                    }
                                }
                                catch (Exception exExportPrices)
                                {
                                    System.IO.File.AppendAllText(System.Web.HttpContext.Current.Server.MapPath("~/Logs/_sageInventoryExportPricesCallError.txt"), exExportPrices.ToString());
                                }
                                break;
                            }
                        }
                    }
                }
                //end foreach

                //return (xmlResult + "</InventoryExportResponse>");
            }

            UpdatePricesFromInventoryListBulk(_inventoryCollection);//this call will update 40000 records in local DB.

            return "Stock prices synched to accounting system!";
        }

public void UpdatePricesFromInventoryListBulk(IList<Domain.Tables.Inventory> invList)
        {
            var db = new UniStockContext();
            db.Configuration.AutoDetectChangesEnabled = false;

            foreach (var inventory in invList)
            {
                Domain.Tables.Inventory _inventory = db.Inventories
                                                    .Single(x => x.InventoryID == inventory.InventoryID);

                if (inventory.Cost.HasValue)
                    _inventory.Cost = inventory.Cost.Value;
                else
                    _inventory.Cost = 0;

                foreach (var inventoryPrices in inventory.AccInventoryPrices)
                {
                    foreach (var _inventoryPrices in _inventory.AccInventoryPrices)
                    {
                        if (_inventoryPrices.AccInventoryPriceID == inventoryPrices.AccInventoryPriceID)
                        {
                            _inventoryPrices.ApplyDiscount = inventoryPrices.ApplyDiscount;
                            _inventoryPrices.ApplyMarkup = inventoryPrices.ApplyMarkup;
                            if (inventoryPrices.Price.HasValue)
                                _inventoryPrices.Price = inventoryPrices.Price.Value;
                            else
                                _inventoryPrices.Price = _inventory.Cost;

                            if (inventoryPrices.OldPrice.HasValue)
                            {
                                _inventoryPrices.OldPrice = inventoryPrices.OldPrice;
                            }
                        }
                    }
                }

                db.Inventories.Attach(_inventory);
                db.Entry(_inventory).State = System.Data.Entity.EntityState.Modified;
            }

            db.SaveChanges();
            db.Dispose();
        }

1 个答案:

答案 0 :(得分:3)

[SiteAccessRules] Rules[]=access;disable # If content/search module use current policy (denied) Rules[]=module;content/search 编写的代码确实可以起作用,但是Thread.Start(...)只是启动了该过程-如果之前花费了几个小时,那么现在可能要花费几个小时。在混合中添加线程不会突然使数据库更快地完成工作。

问题可能出在Thread.Start函数中,但是您说您无法对其进行概要分析,因此我们永远不会知道。如果无法使用任何工具找出程序运行缓慢的位置,则我们无法知道位置程序运行缓慢。

对我来说,将请求处理多个数据库之间的数千行的请求包装到一个函数中的任何事情都无法很好地考虑正在进行的工作。正在执行的操作是关键,并且由于未包含在问题中,因此我们可能无法知道是否是问题所在。

您需要仔细考虑要包装的数据库操作。如果这是性能问题所在,那么您可能需要重新处理该算法中的内容,而不是这个简短的简单函数中的内容。

如果数据库操作没有一次击中任何一个数据库,则有可能您还可以使用.ExportPrices(...)运行这些操作,并使用Thread.Start等待其完成,但这将只允许一次运行多个,而不减少一次完成的时间。