У меня есть приложение для Windows Phone 8, которое использует фоновый агент для:
- Получить данные из интернета;
- Создайте изображение на основе пользовательского элемента управления, который использует данные из шага 1 в качестве источника данных;
- В пользовательском элементе управления у меня есть Grid и StackPanel и некоторые элементы управления текстом и изображением;
- Когда некоторые из изображений используют локальные ресурсы из папки установки (/Assets/images/...), один из них, который я использовал в качестве фона, выбирается пользователем из библиотеки фотографий телефона, поэтому мне нужно установить источник с помощью С# код позади.
Однако, когда он работает в фоновом режиме, он получает OutOfMemoryException
, некоторые проблемы с устранением неполадок:
- Когда я запускаю процесс «спереди», все работает нормально;
- Если я прокомментирую ход обновления и создам образ напрямую, он также будет работать нормально;
- Если я не устанавливаю фоновое изображение, оно также работает нормально;
OutOfMemoryException
был выброшен во времяvar bmp = new WriteableBitmap(480, 800);
Я уже уменьшил размер изображения с 1280*768 до 800*480, я думаю, что это нижняя граница для полноэкранного фонового изображения, не так ли?- После некоторых исследований я обнаружил, что эта проблема возникает из-за превышения ограничения в 11 МБ для периодической задачи.
Я попытался использовать
DeviceStatus.ApplicationCurrentMemoryUsage
для отслеживания использования памяти:-- ограничение 11 534 336 (бит)
-- при запуске фонового агента, даже без какой-либо задачи в нем, использование памяти становится равным 4 648 960
-- При получении обновления из Интернета оно выросло до 5 079 040.
-- по завершении оно упало до 4 648 960
-- Когда начался вызов (для создания изображения из пользовательского элемента управления), он вырос до 8 499 200
Ну, я думаю, в этом проблема, мало памяти для рендеринга изображения через WriteableBitmap
.
Любая идея, как решить эту проблему?
Есть ли лучший способ создать изображение из пользовательского элемента управления/или чего-либо еще?
На самом деле исходное изображение может быть всего 100 КБ или около того, однако при рендеринге с помощью WriteableBitmap
размер файла (а также объем необходимой памяти, я думаю) может вырасти до 1-2 МБ.
Или я могу освободить память откуда угодно?
==============================================================
Кстати, когда эта статья Code Project говорит, что я могу использовать только 11 МБ памяти в периодической задаче;
Однако эта статья MSDN говорит, что я могу использовать до 20 МБ или 25 МБ с Windows Phone 8 Update 3; Что правильно? И почему я в первой ситуации?
==============================================================
Редактировать:
Говоря об отладчике, он также указан в Статья MSDN:
When running under the debugger, memory and timeout restrictions are suspended.
Но зачем мне все-таки нажимать на ограничение?
==============================================================
Редактировать:
Что ж, я нашел кое-что, похоже, полезное, сейчас я проверю их, предложения по-прежнему приветствуются.
http://writeablebitmapex.codeplex.com/
http://suchan.cz/2012/07/pro-live-tiles-for-windows-phone/
http://notebookheavy.com/2011/12/06/microsoft-style-dynamic-tiles-for-windows-phone-mango/
==============================================================
Код для генерации изображения:
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
var customBG = new ImageUserControl();
customBG.Measure(new Size(480, 800));
var bmp = new WriteableBitmap(480, 800); //Thrown the **OutOfMemoryException**
bmp.Render(customBG, null);
bmp.Invalidate();
using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
{
filename = "/Shared/NewBackGround.jpg";
using (var stream = isf.OpenFile(filename, System.IO.FileMode.OpenOrCreate))
{
bmp.SaveJpeg(stream, 480, 800, 0, 100);
}
}
}
Код XAML для ImageUserControl
:
<UserControl blabla... d:DesignHeight="800" d:DesignWidth="480">
<Grid x:Name="LayoutRoot">
<Image x:Name="nBackgroundSource" Stretch="UniformToFill"/>
//blabla...
</Grid>
</UserControl>
Код С#, стоящий за ImageUserControl
:
public ImageUserControl()
{
InitializeComponent();
LupdateUI();
}
public void LupdateUI()
{
DataInfo _dataInfo = new DataInfo();
LayoutRoot.DataContext = _dataInfo;
try
{
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var isoFileStream = isoStore.OpenFile("/Shared/BackgroundImage.jpg", FileMode.Open, FileAccess.Read))
{
BitmapImage bi = new BitmapImage();
bi.SetSource(isoFileStream);
nBackgroundSource.Source = bi;
}
}
}
catch (Exception) { }
}
Когда DataInfo
является другим классом в страница настроек, содержащая данные, получаемые из Интернета:
public class DataInfo
{
public string Wind1 { get { return GetValueOrDefault<string>("Wind1", "N/A"); } set { if (AddOrUpdateValue("Wind1", value)) { Save(); } } }
public string Wind2 { get { return GetValueOrDefault<string>("Wind2", "N/A"); } set { if (AddOrUpdateValue("Wind2", value)) { Save(); } } }
//blabla...
}