2012-02-13 1 views
0

У меня есть сомнения, что эта часть кода вызывает утечку памяти:Как обнаружить утечку память

public FileResult ShowCroppedImage(int id, int size) 
    { 
     string path = "~/Uploads/Photos/"; 
     string sourceFile = Server.MapPath(path) + id + ".jpg"; 

     MemoryStream stream = new MemoryStream(); 
     var bitmap = imageManipulation.CropImage(sourceFile, size, size); 
     bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); 
     Byte[] bytes = stream.ToArray(); 
     return File(bytes, "image/png"); 
    } 

Как я мог бы сделать тест, чтобы увидеть, если этот кусок кода является причиной?

EDIT:

public Image CropImage(string sourceFile, int newWidth, int newHeight) 
     { 
      Image img = Image.FromFile(sourceFile); 
      Image outimage; 

      int sizeX = newWidth; 
      int sizeY = newHeight; 

      MemoryStream mm = null; 

      double ratio = 0; 
      int fromX = 0; 
      int fromY = 0; 

      if (img.Width < img.Height) 
      { 
       ratio = img.Width/(double)img.Height; 
       newHeight = (int)(newHeight/ratio); 
       fromY = (img.Height - img.Width)/2; 
      } 
      else 
      { 
       ratio = img.Height/(double)img.Width; 
       newWidth = (int)(newWidth/ratio); 
       fromX = (img.Width - img.Height)/2; 
      } 
      if (img.Width == img.Height) 
       fromX = 0; 

      Bitmap result = new Bitmap(sizeX, sizeY); 

      //use a graphics object to draw the resized image into the bitmap 
      Graphics grPhoto = Graphics.FromImage(result); 

      //set the resize quality modes to high quality 
      grPhoto.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 
      grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 
      grPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 
      //draw the image into the target bitmap 
      //now do the crop    
      grPhoto.DrawImage(
       img, 
       new System.Drawing.Rectangle(0, 0, newWidth, newHeight), 
       new System.Drawing.Rectangle(fromX, fromY, img.Width, img.Height), 
       System.Drawing.GraphicsUnit.Pixel); 


      // Save out to memory and get an image from it to send back out the method. 
      mm = new MemoryStream(); 
      result.Save(mm, System.Drawing.Imaging.ImageFormat.Jpeg); 
      img.Dispose(); 
      result.Dispose(); 
      grPhoto.Dispose(); 
      outimage = Image.FromStream(mm); 

      return outimage; 
     } 
+2

Простой способ: выстроить свою программу для повторного вызова этого кода, а затем наблюдать за процессом в диспетчере задач. Если используемая память продолжает расти и никогда не падает, тогда у вас есть утечка. – Blorgbeard

+2

http://mitch-wheat.blogspot.com.au/2010/11/determine-if-your-net-application-has.html –

+1

Единственное, что вы можете сделать здесь, это обернуть MemoryStream в используемый блок для утилизации это автоматически. Почему, по-вашему, есть утечка памяти. Пожалуйста, сообщите нам, что находится внутри imageManipulation.CropImage. Вы закрываете неуправляемые ручки? – abhishek

ответ

3

Я пишу это как

public FileResult ShowCroppedImage(int id, int size) 
{ 
    string path = "~/Uploads/Photos/"; 
    string sourceFile = Server.MapPath(path) + id + ".jpg"; 

    using (MemoryStream stream = new MemoryStream()) 
    { 
     using (Bitmap bitmap = imageManipulation.CropImage(sourceFile, size, size)) 
     { 
      bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg); 
      Byte[] bytes = stream.ToArray(); 
      return File(bytes, "image/png"); 
     } 
    } 
} 

, чтобы гарантировать, что stream.Dispose & bitmap.Dispose называются.

+0

«Использование (MemoryStream = ...)» - это просто ритуал, использование вокруг Bitmap представляется более актуальным. –

+1

@HenkHolterman, Да, это ритуал, но хорошая привычка. –

+2

Утилизация всего, что реализует IDisposable, когда вам больше не нужно, это ВСЕГДА хорошая практика. Не имеет значения, если на практике это происходит только потому, что другие реализации нуждаются в этой способности; если это IDisposable, утилизируйте его. – KeithS

0

Можете позвонить по телефону stream.dispose(); после Byte[] bytes = stream.ToArray();.

0

Учитывая вопрос, как обнаружить утечки памяти/использование, я рекомендовал бы писать метод, который вызывает вашу функцию записи использования памяти до и после:

public void SomeTestMethod() 
{ 
    var before = System.GC.GetTotalMemory(false); 
    // call your method 
    var used = before - System.GC.GetTotalMemory(false); 
    var unreclaimed = before - System.GC.GetTotalMemory(true); 
} 

Перед измерит использование памяти, прежде чем ваш функция работает. Используемая переменная будет содержать количество памяти, используемое вашей функцией до того, как сборщик мусора будет запущен и не будет восстановлен, сообщит вам, сколько байтов используется вашей функцией даже после попытки очистки ваших объектов.

Я подозреваю, что используемое будет высоким и невосприимчивым, не будет - использование использования вокруг вашего потока памяти, как предлагают другие плакаты, должно сделать их ближе, хотя помните, что у вас все еще есть массив байтов, удерживающий память.