2015-08-21 4 views
0

Я реализую небольшой просмотрщик изображений, к сожалению, я сталкиваюсь с утечкой памяти. Ниже приведен порядок загрузки.C# Image loader memory leak

public BitmapSource getImage(string fileName, double width, double height) 
    { 
     FileStream s = File.Open(fileName, FileMode.Open); 
     Image i = Image.FromStream(s, false, false); 
     double iWidth = i.Width; 
     double iHeight = i.Height; 
     i.Dispose(); 
     s.Close(); 

     BitmapImage tmpImage = new BitmapImage(); 
     tmpImage.BeginInit(); 
     tmpImage.CacheOption = BitmapCacheOption.OnLoad; 
     tmpImage.UriSource = new Uri(fileName); 
     if (iWidth > iHeight) 
     { 
      tmpImage.DecodePixelWidth = (int)width; 
     } 
     else 
     { 
      tmpImage.DecodePixelHeight = (int)height; 
     } 
     tmpImage.EndInit(); 
     return tmpImage; 
    } 

Это, как я называю Загрузчик

private void whenArrowKeyPressed(int index) 
{ 
    CurrentImage = fh.getImage(fileList[index], 1920, 1080); 
} 

CurrentImage это свойство, которое связано с WPF ViewBox.

Любые идеи? Я также попытался прочитать StreamSource с тем же эффектом.

+0

Вы не располагаете FileStream. Вызовите s.Dispose() вместо s.Close(); Dispose также позаботится о закрытии. –

+0

Спасибо, я мог видеть некоторое улучшение. К сожалению, это не решение проблемы полностью. При показе первого изображения приложение использует ок. 150MB, после переключения несколько раз, я вижу теперь повышение до ca, 300MB – user5230928

+0

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

ответ

0

Только проблема, которую я мог видеть, это то, что вы не используете FileStream. BitmapImage не одноразовый, и он освободит свою память, если нет ссылок на нее.

Как вы обнаружили, что происходит утечка памяти? Рекомендуется использовать инструмент профилирования. Сборщик мусора не выпускает память, когда что-то выходит из сферы действия, она ожидает, что использование памяти превысит определенные пороговые значения (обычно, когда Gen 0 будет превышать порог). Таким образом, вы увидите некоторое увеличение памяти, и оно освободит память только после того, как сборщик мусора выполнит.

Видимо, вы не используете инструмент для профилирования. В этом случае, если вы хотите проверить, есть ли утечка памяти, вы можете вручную выполнить GC.Collect и дождаться завершения, прежде чем вы получите чтение памяти. Имейте в виду, что вам не нужно вручную выполнять GC.Collect, поскольку это будет происходить автоматически оптимизированным образом, когда это необходимо.

public BitmapSource getImage(string fileName, double width, double height) 
    { 
     using(FileStream s = File.Open(fileName, FileMode.Open)) 
     using(Image i = Image.FromStream(s, false, false)) 
     { 
      double iWidth = i.Width; 
      double iHeight = i.Height;     
     } 

     BitmapImage tmpImage = new BitmapImage(); 
     tmpImage.BeginInit(); 
     tmpImage.CacheOption = BitmapCacheOption.OnLoad; 
     tmpImage.UriSource = new Uri(fileName); 
     if (iWidth > iHeight) 
     { 
      tmpImage.DecodePixelWidth = (int)width; 
     } 
     else 
     { 
      tmpImage.DecodePixelHeight = (int)height; 
     } 
     tmpImage.EndInit(); 
     return tmpImage; 
    } 

private void whenArrowKeyPressed(int index) 
{ 
    CurrentImage = fh.getImage(fileList[index], 1920, 1080); 

    // Remove this once you finish testing. 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
}