Mam problem wycieków pamięci w mojej aplikacji, który ładuje dużą liczbę obrazów. Jestem raczej nowy w C# i pomyślałem, że minęły moje dni z problemami z wyciekiem pamięci. Nie mogę wymyślić problemu - może używam niektórych niezarządzanych modułów, których nie obsługuję poprawnie?Obrazek wyciek pamięci z C#
Aby zilustrować mój problem, uprościliśmy rdzeń tego, co powoduje problem, i przeniosłem go do czystego projektu. Zauważ, że jest to cały głupi kod, który nie odzwierciedla oryginalnej aplikacji, z której pochodzi. W aplikacji testowej mam 2 przyciski, wyzwalające dwa zdarzenia.
Przycisk 1 - Utwórz: Ustawienie obiektu na format danych. Spowoduje to załadowanie obrazów i zachować je przy życiu przez ustawienie obiekt do DataContext:
var imgPath = @"C:\some_fixed_path\img.jpg";
DataContext = new SillyImageLoader(imgPath);
przycisk 2 - Oczyszczanie: Rozumiem, że jeśli puścić odniesienia trzymając SillyImageLoader który ponownie przechowuje obrazy, a następnie to zostanie usunięte. Wywoływam również jawnie wyrzucanie śmieci tylko po to, aby natychmiast zobaczyć ilość pamięci po usunięciu odwołania.
DataContext = null;
System.GC.Collect();
Podczas testowania ładuję obraz jpeg 974KB. Przechowywanie 30 obrazów bitmapowych zwiększa wykorzystanie pamięci mojej aplikacji z ~ 18 MB do ~ 562 MB. Ok. Ale po wyczyszczeniu pamięci ilość pamięci spada do ~ 292 MB. Jeśli powtórzę Create + CleanUp, pozostawi mi kolejną pamięć ~ 250 MB. Więc oczywiście coś jest nadal w posiadaniu kogoś.
Oto SillyImageLoader-code:
namespace MemoryLeakTest
{
using System;
using System.Drawing;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
public class SillyImageLoader
{
private BitmapSource[] _images;
public SillyImageLoader(string path)
{
DummyLoad(path);
}
private void DummyLoad(string path)
{
const int numberOfCopies = 30;
_images = new BitmapSource[numberOfCopies];
for (int i = 0; i < numberOfCopies; i++)
{
_images[i] = LoadImage(path);
}
}
private static BitmapSource LoadImage(string path)
{
using (var bmp = new Bitmap(path))
{
return Imaging.CreateBitmapSourceFromHBitmap(
bmp.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
}
}
}
Jakieś pomysły? Problem wydaje się być związany z BitmapSource. Trzymając tylko bitmapę, nie ma wycieku pamięci. Używam BitmapSource, aby móc ustawić to na właściwość Source obrazu. Czy powinienem zrobić to inaczej? Jeśli tak, nadal chciałbym znać odpowiedź na wyciek pamięci.
Dzięki.
Kto dzwoni Pozbyć się BitmapSource zwrócony z LoadImage? –
Pomyślałem o tym, rzeczywiście opublikowałem odpowiedź na podstawie tego, ale nie widzę dyspozycji na BitmapSource (usunąłem odpowiedź) –
W jaki sposób monitorujesz wykorzystanie pamięci przez twoją aplikację? Menadżer zadań? –