0

Мое приложение CF имеет очень настраиваемый пользовательский интерфейс, используя множество изображений в качестве элементов пользовательского интерфейса. Пользовательский интерфейс чувствует себя намного более гладким, когда эти растровые изображения хранятся в памяти. Когда они загружаются по требованию, пользовательский интерфейс работает медленно, и я вижу кнопки, появляющиеся один за другим, что выглядит очень плохо. Долгое время это прошло довольно хорошо, но в последнее время я обнаружил, что приложение почти использует всю память, которую он может получить, это 32 МБ iirc. Затем я начал использовать удаленный монитор производительности, чтобы узнать, могу ли я найти чистых ящиков памяти.Рекомендации по решению OutOfMemoryExceptions для CF

Как оказалось, получение полезного моментального снимка кучи GC с использованием RPM затруднено: закрытие до того, как я получу исключения из памяти, запрос на моментальный снимок вызывает немедленное генерирование собственного исключения. Тем не менее, я могу найти моментальный снимок GC. Я сохранил его здесь: http://files.zzattack.org/misc/ramis.gclog и скриншот здесь: http://files.zzattack.org/images/ramisgcsnapshot.png Для меня это не выглядит все, что хлопотно, но самым большим объектом является массив байтов, содержащий мой файл ресурсов (около 3 МБ, полный изображений PNG). Используется Alltogeher, 3643304b (около 3,5 МБ) памяти. Эти изображения распространяются по элементам пользовательского интерфейса примерно в 20 различных формах. Я не знаю, какое влияние оказывают отдельные потоки на использование памяти, но одновременно работает около 5-6 потоков, из которых по крайней мере 4 находятся в заблокированном состоянии в 95% случаев.

В программе, когда я пытаюсь загрузить файл с размером 2 МБ, я всегда получаю исключение OutOfMemoryException. Когда я вызываю GC.GetTotalMemory (false), я вижу, что я действительно пытаюсь выделить больше, чем доступно в настоящее время. Вызов GC.Collect и повторная попытка не решают/откладывают мою проблему.

Я хотел бы посоветовать, как решить мою проблему. Мне абсолютно нужны растровые изображения в памяти, но, возможно, я мог бы ограничить количество слотов, доступных для растровых изображений, сохраняя только наиболее часто используемые в памяти и загружая другие по требованию. Вероятно, это длинный снимок, но, возможно, я могу попросить ОС зарезервировать для меня больше памяти? Я точно знаю, что приложение будет работать только на устройствах с достаточным объемом оперативной памяти. Любая помощь приветствуется, спасибо заранее.

ответ

1

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

public class AppBitmaps 
{ 
    public static Bitmap LogoBitmap = new Bitmap(...); 

    public static Bitmap ButtonBitmap = new Bitmap(...); 
} 

public class Form1 
{ 
    public Form1() 
    { 
    this.Control1.Image = AppBitmaps.LogoBitmap; 
    } 
} 

Таким образом, вы сохраняете только один экземпляр этого изображения в памяти, что должно сократить общее использование памяти.

+0

Спасибо за ваш комментарий. В старой ситуации я много раз вызывал ResourceManager.GetObject() для загрузки моих растровых изображений. Поскольку мне нужны были очень незначительные варианты локализации и масштабирования (т. Е. Иногда разные разрешения WVGA/VGA изображения), все было получено с помощью статической вспомогательной функции. Таким образом было очень легко добавить механизм кэширования, как вы предложили в этой вспомогательной функции, что привело к сохранению нескольких растровых изображений в памяти. Пока этого хватит, так что спасибо! –

0

«Получение полезного моментального снимка кучи GC с использованием RPM сложно» Возможно, вы можете попробовать профайлер для .NET CF, я слышал о профилировщике EQATEC, если это поможет вам в потоках.

. Мой подход к исключению ошибок OOM заключается в том, чтобы не создавать приложения типа MDI (Multiple Document Interface), иметь только одну форму в памяти) и устанавливать нулевые объекты после их использования (особенно «более тяжелые») как XMLDocument).

Кроме того, это может иметь отношения: OutOfMemoryException When Creating a Large Bitmap in CF.NET

+0

Кэширование формы и вместо закрытия/воссоздавать их на лету результаты в гораздо более плавный переход при переключении формы. Поэтому я хочу сохранить свой дизайн с сильно кэшированными формами. Раньше я использовал профилировщик EQATEC, но, как я помню, он не записывает следы памяти. Первая строка описания продукта подтвердит это: «EQATEC Profiler - это профилировщик кода, а не профилировщик памяти». –

0

Если это моментальный снимок вашего приложения, работающего на полную мощность, то я хотел бы предложить:

  • Это другое приложение, которое работает
  • Ваше приложение pinvokes в неуправляемый памяти утечки
  • ОС (настроенный CE?) Имеет просачиваться
  • или что-то еще
+0

На самом деле у моего устройства имеется много оперативной памяти. Я использую стандартное профессиональное устройство WM6, не имею ничего, кроме основных процессов, и мой код имеет очень мало функций P/Invoke, которые обычно вызывают только один раз. Я думаю, что это вместо этого связано с пределом адресного пространства 32 МБ, с которым нужно иметь дело с приложениями winmo. –

+0

Я думал, что ограничение не распространяется на WM6? Я знаю, что это определенно на WM5. В любом случае я забыл, что вам также необходимо добавить размер GC Heap и различные кеши CLR к вашему счету (который вы можете получить от профилировщика). Затем размер .dlls (несжатый) на этом, чтобы получить окончательный результат. – Quibblesome

Смежные вопросы