处理 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
并将其存储在名为 DataFile
的 List<DriveTimeObject>
中。假设您的 DataQuery
中有 60 万个项目,这意味着您的列表也包含 60 万个项目。
但是,您根本没有使用该列表,因此它无缘无故地占用了您的所有内存。删除它并为自己节省一整吨内存,它也应该 运行 快得多。
防止内存不足的方法就是不要运行内存不足。这意味着您需要摆脱不需要的对象。
如果不进一步了解您的用例,就很难提出修复建议。不管怎样,内存中有太多对象以至于 运行 退出并崩溃是一种不好的做法。 只记住你需要的东西。
一个解决方法是不使用 RAM 内存,而是使用硬盘内存。例如:您可以将这些对象写入数据库并删除它们,这样您就不会保留它们。考虑到您有 600k 个对象,您可以分批处理 10k/25k 记录。然后当你需要这些对象时,你可以查询它们。如果您需要对所有对象进行计算,我建议您使用 SQL 查询来执行这些操作。
在遍历一个大列表并从该列表中添加对象时,是否有适当的方法来处理内存不足异常?这样做的正确方法是什么?我有一个大型 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
并将其存储在名为 DataFile
的 List<DriveTimeObject>
中。假设您的 DataQuery
中有 60 万个项目,这意味着您的列表也包含 60 万个项目。
但是,您根本没有使用该列表,因此它无缘无故地占用了您的所有内存。删除它并为自己节省一整吨内存,它也应该 运行 快得多。
防止内存不足的方法就是不要运行内存不足。这意味着您需要摆脱不需要的对象。
如果不进一步了解您的用例,就很难提出修复建议。不管怎样,内存中有太多对象以至于 运行 退出并崩溃是一种不好的做法。 只记住你需要的东西。
一个解决方法是不使用 RAM 内存,而是使用硬盘内存。例如:您可以将这些对象写入数据库并删除它们,这样您就不会保留它们。考虑到您有 600k 个对象,您可以分批处理 10k/25k 记录。然后当你需要这些对象时,你可以查询它们。如果您需要对所有对象进行计算,我建议您使用 SQL 查询来执行这些操作。