我的應用程序具有一項功能,可以從中導出數據庫中的數據。它使用Ionic ZIP庫構建一個包含數據的zip文件。構建Zip文件時減少內存使用量
該過程通過檢索每個1,000行的頁面中的數據來工作。檢索的數據包含每行數據2個圖像(JPEGS)。 「導出」由HTML文件和HTML表格組成。該表包含每行的重要信息和圖像的鏈接。每個圖像都以JPEG文件形式存儲在ZIP文件中。寫入的HTML包含一個鏈接到適當圖像文件的錨標記。
一切正常,但我最近發現導出大量行時發生OutOfMemoryException
(在發現問題的情況下超過24,000)。在看我的代碼,我沒有看到任何明顯的滲漏(否則我不會被張貼這一點,我會;?))
這裏是正在導出的數據輸出的方法:
private void OutputReads(StreamWriter writer, ZipFile zipFile, BackgroundWorker worker, ExportArgs args) {
int ReadCount = Math.Min(args.ReadMatches, args.ResultsLimit);
writer.WriteLine("<h2>Matching Reads:</h2>");
writer.WriteLine("<p>Number in Database: {0}</p>", args.ReadMatches.ToString("#,##0"));
writer.WriteLine("<p>Number in Report: {0}</p>", ReadCount .ToString("#,##0"));
writer.WriteLine();
if (args.ReadMatches == 0) {
return;
}
writer.WriteLine("<table border=\"1\" cellspacing=\"0\" bordercolordark=\"black\" bordercolorlight=\"black\">");
writer.WriteLine("<tr>");
writer.WriteLine("<th width=\"110\"><b>Plate</b></th>");
writer.WriteLine("<th width=\"60\"><b>State</b></th>");
writer.WriteLine("<th width=\"200\"><b>Date/Time</b></th>");
writer.WriteLine("<th width=\"142\"><b>Latitude</b?</th> ");
writer.WriteLine("<th width=\"142\"><b>Longitude</b?</th> ");
writer.WriteLine("<th width=\"125\"><b>Alarm Class</b></th>");
writer.WriteLine("<th width=\"150\"><b>Notes</b></th>");
writer.WriteLine("<th width=\"150\"><b>Officer Notes</b></th>");
writer.WriteLine("<th width=\"150\"><b>Images</b></th>");
writer.WriteLine("</tr>");
int noPages = ReadCount/args.PageSize + (ReadCount % args.PageSize == 0 ? 0 : 1);
for (int pageNo = 0, count = 0; pageNo < noPages; pageNo++) {
if (worker.CancellationPending) {
return;
}
ReadViewModel[] reads = null;
try {
reads = DataInterface.GetReads(args.LocaleCode, args.Plate,
args.StartDate, args.EndDate,
args.AlarmClasses, args.HotListId,
args.PageSize, pageNo
);
} catch (DataAccessException ex) {
. . .
} catch (ThreadAbortException) {
// The thread is stopping. Stop processing now.
} catch (Exception ex) {
. . .
}
foreach (ReadViewModel read in reads) {
if (worker.CancellationPending) {
return;
}
writer.WriteLine("<tr>");
writer.WriteLine("<td width=\"110\"><p align=\"left\" style=\"text-align:left\">{0}</p></td>" , read.Plate);
writer.WriteLine("<td width=\"60\" ><p align=\"center\" style=\"text-align:center\">{0}</p></td>", read.State);
writer.WriteLine("<td width=\"150\"><p align=\"center\" style=\"text-align:center\">{0}</p></td>", read.TimeStamp);
writer.WriteLine("<td width=\"125\"><p align=\"center\" style=\"text-align:center\">{0}</p></td>", read.GPSInformation == null ? " " : read.GPSInformation.Position.Latitude.ToString( "##0.000000"));
writer.WriteLine("<td width=\"125\"><p align=\"center\" style=\"text-align:center\">{0}</p></td>", read.GPSInformation == null ? " " : read.GPSInformation.Position.Longitude.ToString("##0.000000"));
writer.WriteLine("<td width=\"125\"><p align=\"center\" style=\"text-align:center\">{0}</p></td>", read.AlarmClass == null ? " " : read.AlarmClass);
writer.WriteLine("<td width=\"150\"><p align=\"left\" style=\"text-align:left\">{0}</p></td>" , read. Notes == null ? " " : read. Notes);
writer.WriteLine("<td width=\"150\"><p align=\"left\" style=\"text-align:left\">{0}</p></td>" , read.OfficerNotes == null ? " " : read.OfficerNotes);
if (read.ImageData == null) {
try {
DataInterface.GetPlateImage(read);
} catch (DataAccessException ex) {
. . .
} catch (Exception ex) {
. . .
}
}
if (read.OverviewImages == null) {
try {
DataInterface.GetOverviewImages(read);
} catch (DataAccessException ex) {
. . .
} catch (Exception ex) {
. . .
}
}
if (read.ImageData != null) {
string ext = LPRCore.CarSystem.ImageDataAccessor.GetImageFileExtension(read.ImageData);
writer.Write("<td width=\"150\"><p align=\"left\" style=\"text-align:left\"><a href=\".\\Images\\{0}.{1}\" target=\"_blank\">BW</a>", read.ID.ToString("N"), ext);
string fileName = string.Format(".\\Images\\{0}{1}", read.ID.ToString("N"), ext);
if (!zipFile.ContainsEntry(fileName)) {
zipFile.AddEntry(fileName, read.ImageData);
}
} else {
writer.Write("No Plate Image");
}
if (read.OverviewImages != null && read.OverviewImages.Length > 0) {
for (int i = 0; i < read.OverviewImages.Length; i++) {
string ext = LPRCore.CarSystem.ImageDataAccessor.GetImageFileExtension(read.OverviewImages[ i ].ImageData);
writer.Write(" - <a href=\".\\Images\\{0}_C{1}{2}\" target=\"_blank\">Color {1}</a>", read.ID.ToString("N"), i == 0 ? string.Empty : i.ToString(), ext);
string fileName = string.Format(".\\Images\\{0}_c{1}{2}", read.ID.ToString("N"), i == 0 ? string.Empty : i.ToString(), ext);
if (!zipFile.ContainsEntry(fileName)) {
zipFile.AddEntry(fileName, read.OverviewImages[ i ].ImageData);
}
}
} else {
writer.Write("No Overview Images");
}
writer.WriteLine("</p></td>");
writer.WriteLine("</tr>");
count++;
worker.ReportProgress(count, args);
}
}
writer.WriteLine("</table>");
writer.WriteLine();
}
我在想,也許Zip文件是問題,因爲它沒有被刷新到磁盤或類似的東西上,並且隨着行的處理而變得越來越大。
有沒有一種方法可以將zip文件刷新到磁盤並釋放所有圖像,以便垃圾回收器將它們釋放,或者有另一種方法使用此庫使用較少的內存來構建zip文件?