Я использую приведенный ниже код для создания живой плитки, основанной на элементе пользовательского интерфейса.
Он отображает uiElement
на WriteableBitmap
, сохраняет битмап +, возвращает имя файла.
Этот метод запускается в операторе заданий фона телефона Windows, и я бегу в пределы памяти.
private string CreateLiveTileImage(Canvas uiElement, int width, int heigth)
{
var wbmp = new WriteableBitmap(width, heigth);
try
{
wbmp.Render(uiElement, null);
wbmp.Invalidate();
var tileImageName = _liveTileStoreLocation;
using (var stream = new IsolatedStorageFileStream(tileImageName, FileMode.Create, FileAccess.Write, IsolatedStorageFile.GetUserStoreForApplication()))
{
wbmp.SaveJpeg(stream, width, heigth, 0, 100);
stream.Close();
}
uiElement = null;
wbmp = null;
GC.Collect();
return "isostore:" + tileImageName;
}
catch (Exception exception)
{
// ...
}
return null;
}
Я провел некоторое тестирование, и проблема в том, что эти методы утечки памяти, но я не знаю почему/где?!
Я также проделал некоторые тестовые прогоны - перед первым запуском этого метода:
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
7.249.920 Bytes
Это нормально, так как отладчик подключен, который использует около 2 МБ памяти.
Выполнение еще нескольких прогонов этого метода (снова установите метод запуска в отладчик):
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
8851456 long + 40960
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
8892416 long + 245760
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9138176 long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9281536 long + 151552
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9433088 long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9576448 long + 139264
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9715712 long + 139264
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9859072 long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
10006528 long + 147456
Таким образом, память, используемая этим методом, увеличивается.
Но почему? По-моему, нет ссылок, которые мешают собирать объекты.
ОБНОВЛЕНИЕ 04.05.2013
Привет,
Благодарю вас за все ваши ответы! Как было предложено, я уменьшил код +, в конце концов, смог воспроизвести проблему в нескольких строках кода.
void Main()
{
for (int i = 0; i < 100; i++)
{
CreateImage();
}
}
private void CreateImage()
{
var rectangle = CreateRectangle();
var writeableBitmap = new WriteableBitmap(rectangle, rectangle.RenderTransform);
rectangle = null;
writeableBitmap = null;
GC.Collect();
}
private Rectangle CreateRectangle()
{
var solidColorBrush = new SolidColorBrush(Colors.Blue);
var rectangle = new Rectangle
{
Width = 1000,
Height = 1000,
Fill = solidColorBrush // !!! THIS causes that the image writeableBitmap never gets garbage collected
};
return rectangle;
}
После запуска приложения: ApplicationCurrentMemoryUsage: "11 681 792 байт"
1 Итерация - ApplicationCurrentMemoryUsage: "28 090 368 байт"
5 Итерации - ApplicationCurrentMemoryUsage: "77 111 296 байт"
20 Итерации - ApplicationCurrentMemoryUsage: "260 378 624 байтов"
После 23 итераций: исключение из памяти. Ln.: var writeableBitmap = new WriteableBitmap (прямоугольник, прямоугольник .RenderTransform);
Только комментируя строку "Fill = solidColorBrush", метод CreateImage() был вызван 100 раз без проблем - после 100-й итерации использование памяти было около "16 064 512 байтов".
Итак, проблема в кисти! Когда используется для заполнения элемента пользовательского интерфейса, и позже этот элемент пользовательского интерфейса отображается на записываемом растровом изображении, битмап никогда не получает сбор мусора.
Конечно, это не имеет никакого смысла, на мой взгляд. Кисть выходит из области, поэтому она тоже должна быть собрана мусором! (Установка кисти в значение null после ее использования ничего не изменила)
Многие элементы моего пользовательского интерфейса используют кисть для заполнения, поэтому я не могу просто удалить использование кистей. Что вы думаете об этой проблеме?