处理 OutOfMemory 异常

Dealing with OutOfMemory Exception

在遍历一个大列表并从该列表中添加对象时,是否有适当的方法来处理内存不足异常?这样做的正确方法是什么?我有一个大型 Linq 查询 returns 大约 60 万个项目。然后我遍历每个项目并将其添加到一个对象中。代码如下。

  static void Main(string[] args)
    {
        GrabData();
    }

    public static void GrabData()
    {
        decimal? TotalNetClaim = 0;
        using (var Context = new VSCMeSnapEntities())
        {              
            List<DriveTimeObject> DataFile = new List<DriveTimeObject>(); 
            DriveTimeObject DT = new DriveTimeObject();
            DateTime ParamDate = new DateTime(2015, 05, 30);
            List<viewDriveTimeFileDump> DataQuery = new List<viewDriveTimeFileDump>();

            DataQuery = (from z in Context.viewDriveTimeFileDumps select z).ToList();

            foreach (var item in DataQuery)
            {
                decimal? AmountChargedParts = DT.GetAmountChargedParts(item.chrComponSts.Trim(), item.mnsTotalParts);
                decimal? AmountChargedPartsTax = DT.GetAmountChargedPartsTax(item.chrComponSts.Trim(), item.mnsTotalPartTax);
                decimal? AmountChargedLabor = DT.GetAmountChargedLabor(item.chrComponSts.Trim(), item.mnsTotalLabor);
                decimal? AmountChargedLaborTax = DT.GetAmountChargedLaborTax(item.chrComponSts.Trim(), item.mnsTotalLaborTax);
                int? DaysOut = DT.GetDaysOutClaim(item.intRepairFacilCode, item.dtmContPurchDate, item.dtmReported);
                long? MilesOut = DT.GetMilesOutClaim(item.intRepairFacilCode, item.inbIncurMiles, item.inbOrigMiles);
                decimal? deductible = DT.GetDeductible(item.chrContSts, item.mnsDeduct);
                decimal? netClaim = DT.GetNetClaim(item.chrComponSts.Trim(), item.mnsTotalParts, item.mnsTotalPartTax, item.mnsTotalLabor, item.mnsTotalLaborTax, item.mnsDeduct);

                DataFile.Add(new DriveTimeObject
                {
                    DealerNumber = item.chrDlrNum,
                    VSCName = item.chvVSCName,
                    IcLocationNumber = item.IcLocationNumber,
                    IcRegion = item.IcRegion,
                    Identifier = item.chrIdentifier,
                    ContractNumber = item.chrContNum,
                    VIN = item.chrVIN,
                    CoverageCode = item.CvgCode,
                    ClaimNum = item.intClaimNum,
                    OriginalMiles = item.inbOrigMiles,
                    ContractPurchaseDate = item.dtmContPurchDate,
                    IncurMiles = item.inbIncurMiles,
                    DateReported = item.dtmReported,
                    DaysOutClaim = DaysOut,
                    MilesOut = MilesOut,
                    RepairFacilityNumber = item.intRepairFacilCode,
                    FacilityName = item.chvFacilityName,
                    ZipFive = item.chrZipFive,
                    FacilityAdvisor = item.chrFacilAdvisor,
                    ComponentStatus = item.chrComponSts,
                    ComponentStatusWord = item.ComponDesc,
                    ComponentCode = item.chrComponCode,
                    StatusMasterDescription = item.MasterDesc,
                    ComponentDescription = item.chvComponDesc,
                    Parts = AmountChargedParts,
                    PartsTax = AmountChargedPartsTax,
                    Labor = AmountChargedLabor,
                    LaborTax = AmountChargedLaborTax,
                    Deductible = deductible,
                    NetClaim = netClaim,
                    CarrierCode = item.intCarrierCode,
                    NetworkStatus = item.NetworkStatus,
                    AddOn = item.chrAddOn,
                    ETCDate = item.ETC,
                    ATCDate = item.ATC,
                    LaborTime = item.reaLaborTime,
                    PaidDate = item.dtmPdDate,
                    PaymentID = item.intPaymentID,
                    BatchNumber = item.intBatchNum

                });

                TotalNetClaim += netClaim;
            }
            Context.Dispose();
        }

        Console.WriteLine(TotalNetClaim);
        Console.ReadKey();


    }

我 运行 在 foreach 循环期间内存不足,我想知道我应该如何调整我的代码以使其工作。

您正在创建一个新的 DriveTimeObject 并将其存储在名为 DataFileList<DriveTimeObject> 中。假设您的 DataQuery 中有 60 万个项目,这意味着您的列表也包含 60 万个项目。

但是,您根本没有使用该列表,因此它无缘无故地占用了您的所有内存。删除它并为自己节省一整吨内存,它也应该 运行 快得多。

防止内存不足的方法就是不要运行内存不足。这意味着您需要摆脱不需要的对象。

如果不进一步了解您的用例,就很难提出修复建议。不管怎样,内存中有太多对象以至于 运行 退出并崩溃是一种不好的做法。 只记住你需要的东西。

一个解决方法是不使用 RAM 内存,而是使用硬盘内存。例如:您可以将这些对象写入数据库并删除它们,这样您就不会保留它们。考虑到您有 600k 个对象,您可以分批处理 10k/25k 记录。然后当你需要这些对象时,你可以查询它们。如果您需要对所有对象进行计算,我建议您使用 SQL 查询来执行这些操作。