C# 内存泄漏通过图像循环到字节数组
我有一个例行程序,扫描文件夹中的图像,然后针对每个图像,将其转换为缩略图,然后将缩略图上载到数据库。只有在数据库中没有该特定文件夹的任何项目时,它才会运行。我的问题是,我在处理了几个文件夹后收到内存不足异常,我不确定泄漏发生在哪里。我已经尝试过处理循环中的所有可丢弃的东西,但很明显有些东西仍然从裂缝中掉落C# 内存泄漏通过图像循环到字节数组,c#,image,memory-leaks,bytearray,C#,Image,Memory Leaks,Bytearray,我有一个例行程序,扫描文件夹中的图像,然后针对每个图像,将其转换为缩略图,然后将缩略图上载到数据库。只有在数据库中没有该特定文件夹的任何项目时,它才会运行。我的问题是,我在处理了几个文件夹后收到内存不足异常,我不确定泄漏发生在哪里。我已经尝试过处理循环中的所有可丢弃的东西,但很明显有些东西仍然从裂缝中掉落 private bool LoadImages(int folderid, int parentid) { ProgressScreen tfrm = new ProgressScreen
private bool LoadImages(int folderid, int parentid) {
ProgressScreen tfrm = new ProgressScreen();
tfrm.Hide();
DataTable mtable = new DataTable();
List<FileInfo> lfile;
mtable = Requests.ProcessSQLCommand(sqlconn, "Select f.ID, f.FolderName,f.FolderPath,f.ParentID,f.Root from Folders f where f.ID = " + folderid);
DataTable ptable = Requests.ProcessSQLCommand(sqlconn, "Select Root from Folders where ID = " + parentid);
if (ptable != null && ptable.Rows.Count > 0) {
if (ptable.Rows[0]["Root"].ToString().ToLower() == "true") {
return false;
}
}
bool process = true;
DirectoryInfo di = new DirectoryInfo(mtable.Rows[0]["FolderPath"].ToString());
FileInfo[] smFiles = di.GetFiles("*.jpg", SearchOption.TopDirectoryOnly);
lfile = smFiles.ToList<FileInfo>();
if (lfile.Count <= 0) {
process = false;
}
if (process) {
tfrm.Show(this);
for (int c = 0; c < lfile.Count; c++) {
if (((FileInfo)lfile[c]).Extension == ".txt") {
lfile.RemoveAt(c);
}
if (((FileInfo)lfile[c]).FullName.ToLower().Contains("cover")) {
lfile.RemoveAt(c);
}
}
for (int b = 0; b < lfile.Count; b++) {
Cursor.Current = Cursors.WaitCursor;
this.Enabled = false;
try {
tfrm.Location = new Point((Screen.PrimaryScreen.WorkingArea.Width / 2) - (tfrm.Width / 2), (Screen.PrimaryScreen.WorkingArea.Height / 2) - (tfrm.Height / 2));
} catch {
}
tfrm.SetProgress((int)(((double)(b + 1) / (double)lfile.Count) * 100), "Loading Images", lfile[b].Name.ToString());
tfrm.Refresh();
int recid = 0;
DataTable ttable = Requests.ProcessSQLCommand(sqlconn, "Insert into Image (Name,FolderID,ParentID) VALUES ('" + lfile[b].Name + "'," + folderid + "," + parentid + ") Select SCOPE_IDENTITY()");
if (ttable != null && ttable.Rows.Count > 0) {
recid = int.Parse(ttable.Rows[0][0].ToString());
}
if (recid > 0) {
Image timg = null;
byte[] traw = new byte[0];
traw = File.ReadAllBytes(lfile[b].FullName);
MemoryStream tstream = new MemoryStream(traw);
timg = System.Drawing.Image.FromStream(tstream);
tstream.Dispose();
timg = Requests.FixedSize(timg, 600, 600);
tstream = new MemoryStream();
timg.Save(tstream, System.Drawing.Imaging.ImageFormat.Png);
timg.Dispose();
traw = new byte[0];
traw = tstream.ToArray();
tstream.Dispose();
System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(sqlconn);
con.Open();
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand("Update Image set [Thumb] = Convert(VarBinary(MAX),@Image) where ID = " + recid, con);
cmd.Parameters.AddWithValue("@Image", traw);
cmd.ExecuteNonQuery();
con.Dispose();
}
}
this.Enabled = true;
Cursor.Current = Cursors.Default;
tfrm.Close();
tfrm.Dispose();
System.Windows.Forms.Application.UseWaitCursor = false;
return true;
} else {
return false;
}
}
private bool LoadImages(int-folderid,int-parentid){
ProgressScreen tfrm=新的ProgressScreen();
tfrm.Hide();
DataTable mtable=新DataTable();
列表文件;
mtable=Requests.ProcessSQLCommand(sqlconn,“从文件夹f中选择f.ID、f.FolderName、f.FolderPath、f.ParentID、f.Root,其中f.ID=“+folderid”);
DataTable ptable=Requests.ProcessSQLCommand(sqlconn,“从ID=“+parentid”的文件夹中选择根目录);
如果(ptable!=null&&ptable.Rows.Count>0){
if(ptable.Rows[0][“Root”].ToString().ToLower()=“true”){
返回false;
}
}
布尔过程=真;
DirectoryInfo di=new DirectoryInfo(mtable.Rows[0][“FolderPath”].ToString());
FileInfo[]smFiles=di.GetFiles(“*.jpg”,SearchOption.TopDirectoryOnly);
lfile=smFiles.ToList();
如果(lfile.Count 0){
recid=int.Parse(ttable.Rows[0][0].ToString());
}
如果(recid>0){
图像timg=null;
字节[]traw=新字节[0];
traw=File.ReadAllBytes(lfile[b].FullName);
MemoryStream tstream=新的MemoryStream(traw);
timg=System.Drawing.Image.FromStream(tstream);
tstream.Dispose();
timg=请求.固定大小(timg,600600);
tstream=新内存流();
保存(tstream,System.Drawing.Imaging.ImageFormat.Png);
timg.Dispose();
traw=新字节[0];
traw=tstream.ToArray();
tstream.Dispose();
System.Data.SqlClient.SqlConnection con=new System.Data.SqlClient.SqlConnection(sqlconn);
con.Open();
System.Data.SqlClient.SqlCommand cmd=new System.Data.SqlClient.SqlCommand(“更新图像集[Thumb]=Convert(VarBinary(MAX),@Image),其中ID=“+recid,con”);
cmd.Parameters.AddWithValue(“@Image”,traw);
cmd.ExecuteNonQuery();
con.Dispose();
}
}
this.Enabled=true;
Cursor.Current=Cursors.Default;
tfrm.Close();
tfrm.Dispose();
System.Windows.Forms.Application.UseWaitCursor=false;
返回true;
}否则{
返回false;
}
}
固定尺寸法:
public static Image FixedSize(Image imgPhoto, int Width, int Height) {
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)Width / (float)sourceWidth);
nPercentH = ((float)Height / (float)sourceHeight);
if (nPercentH < nPercentW) {
nPercent = nPercentH;
destX = System.Convert.ToInt16((Width - (sourceWidth * nPercent)) / 2);
} else {
nPercent = nPercentW;
destY = System.Convert.ToInt16((Height - (sourceHeight * nPercent)) / 2);
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.Clear(Color.Magenta);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto, new Rectangle(destX, destY, destWidth, destHeight), new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
公共静态图像固定大小(图像imgPhoto、int-Width、int-Height){
int sourceWidth=imgPhoto.Width;
int sourceHeight=imgPhoto.Height;
int sourceX=0;
int sourceY=0;
int destX=0;
int destY=0;
浮动百分比=0;
浮动nPercentW=0;
浮点数nPercentH=0;
nPercentW=((浮点)宽度/(浮点)源宽度);
nPercentH=((浮动)高度/(浮动)源高度);
如果(nPercentH
原始图像(固定大小之前)的范围从2MB到20MB不等,返回的图像(表中的最大值(len(image))约为750 KB。(编辑:更正的文件大小)
每个文件夹的图像数~100-150
我已经查看并调试过,但找不到导致OOM问题的原因,是否有人可以指出错误,或者为我正在做的事情提供更好的优化?如果这是一个代码审查,我会建议对代码进行许多改进。。。 但无论如何,特别是针对您的问题..您的内存泄漏发生在以下代码行中(请不要将其视为个人问题,但很难发现,因为代码没有那么干净)
这里有2
timg
。一个是原始的,第二个是从请求中得到的。FixedSize
。你传递给请求的timg
。FixedSize
没有得到处理。你可能不是内存不足,而是资源不足。那里有很多东西需要处理ich应该被处理,但可能不会。您可以通过任务管理器查看GDI对象和句柄。FWIW,使用将仔细清理代码。您拥有的最大映像的维度是什么?您是否以32位运行此代码?它是否总是在特定映像上爆炸?正如@VikasGupta指出的,100MB JPG几乎是可以保证的d导致OOM(甚至可能在x64上)由于未压缩图像的大小。@VikasGupta最大的图像是18.3MB 3744x6516x24b,程序编译为64位。不,它不是一个特定的图像,通常是在处理了大约20到30个文件夹之后。在处理了大约100个文件夹之后,它似乎保存得很好。使用Process Explorer,其他控件上似乎还有其他漏洞,但它可能与您发现的相似。
timg = System.Drawing.Image.FromStream(tstream);
tstream.Dispose();
timg = Requests.FixedSize(timg, 600, 600);
....
timg.Dispose();