内存泄漏将图像循环到字节数组

时间:2014-10-04 00:57:53

标签: c# image memory-leaks bytearray

我有一个例程,用于扫描文件夹中的图像,然后为每个图像将其转换为缩略图,然后将该缩略图上传到数据库。只有在db中没有该特定文件夹的任何项目时,它才会运行。我的问题是我在处理了几个文件夹后收到了内存不足异常而且我不确定泄漏发生在哪里。我已经尝试过处理我可以在循环中使用的所有东西,但显然有些东西仍然在裂缝中掉落。

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;
  }
}

固定尺寸​​方法:

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;
}

原始图像(固定大小之前)范围从2MB到20MB,表中返回的图像(max(len(图像))大约为750 KB。(编辑:更正文件大小)

每个文件夹的图像数量~100-150

我已经查看并调试了,但找不到导致OOM问题的原因,是否有人指出错误,或者为我正在做的事情提供更好的优化?

1 个答案:

答案 0 :(得分:0)

如果这是代码审查,那么我会建议许多事情作为此代码的改进...... 但无论如何,特别是你的问题..你的内存泄漏是在以下代码行(请不要亲自接受,但很难发现,因为代码不是那么干净)

      timg = System.Drawing.Image.FromStream(tstream);
      tstream.Dispose();
      timg = Requests.FixedSize(timg, 600, 600);
      ....
      timg.Dispose();

你在这里有 2 timg ..一个是原创的,第二个是你从Requests.FixedSize回来的那个。您传递给timg的{​​{1}} 会被处置。