В частности, вы должны анализировать с этой точки зрения распределение памяти для следующих объектов.
■ Объекты Bitmap. Часто возникают ситуации, в которых в качестве временного хранилища для изображения или части изображения, создаваемых вашим приложением, удобно использовать объект Bitmap. Если вашему приложению требуется пространство для рисования, то в этом нет ничего необычного; единственное, чего следует избегать — так это создания и уничтожения многих битовых изображений в циклах рисования. Обычно гораздо лучше иметь одно рабочее пространство, многократно используемое в качестве общего ресурса, чем нести дополнительные затраты, связанные с непрерывным созданием и уничтожением временных изображений. Размер такой временной памяти должен быть равен размеру наибольшего временного изображения, которое может понадобиться вашим процедурам (но не более того). Если временную память необходимо очищать, прежде чем использовать ее для рисования, то это можно сделать легко и быстро при помощи вызова Graphics.Clear(). Кроме того, как продемонстрировано в приведенном выше примере кода, часто используемые растровые изображения имеет смысл загружать и кэшировать в памяти. Следите за тем, чтобы в каждый момент времени загружался только один экземпляр растрового изображения. Загрузка нескольких экземпляров идентичных изображений приведет к напрасному расходованию больших объемов памяти.
■ Объекты Graphics. Если требуется постоянно перерисовывать растровое изображение, как это, например, приходится делать при перерисовке кадров игрового поля, то, вероятно, наряду с целевым экранным изображением целесообразно кэшировать также объекты Graphics внеэкранных изображений. Поступая таким образом, вы избавитесь от необходимости непрерывного размещения этих объектов в памяти и их удаления. Не распределяйте в циклах рисования память для объектов Graphics растровых изображений или форм более одного раза; в идеальном случае следует вообще избегать размещения и удаления таких объектов внутри циклов. To же самое касается и любых других битовых карт, в которых вы должны выполнять рисование; кэшируйте их объекты Graphics, а не создавайте их каждый раз заново. Учтите, что объекты Graphics нужны только для тех битовых карт, которые вы используете для создания изображений; если битовая карта используется лишь в качестве источника информации об изображении, то объект Graphics для нее вам вообще не нужен.
■ Объекты Font, Brush, Pen, ImageAttribute. Распространенной ошибкой разработчиков, причины которой вполне объяснимы, является их чрезмерное увлечение управлением временем жизни ресурсов на микроуровне, не сопровождающееся глубоким анализом их использования на макроуровне. В процессе создания графического изображения вам может потребоваться пройти, скажем, через 30 отдельных этапов, в ходе которых рисуются линии, закрашиваются эллипсы, создается текст и копируются битовые образы. Выполнение каждой из этих операций требует использования некоторой комбинации перьев, кистей, шрифтов, то есть объектов Pen, Brush, Font, а если в дело включаются еще и маски прозрачности, то и объектов ImageAttribute. В случае мобильных устройств ситуация усугубляется тем, что в .NET Compact Framework, в отличие от .NET Framework, статические версии базовых кистей и перьев не предусмотрены. Так, в версии NET Framework, ориентированной на настольные компьютеры, существуют, например, объекты System.Drawing.Pens.Blue и System.Drawing.Brushes.DarkOrange, но в NET Compact Framework эти объекты приходится распределять. Решение этой проблемы заключается в создании собственного глобального набора объектов Pen и Brush, который вы будете использовать для нужд рисования во всем приложении. Вы должны тщательно просмотреть все циклы рисования в приложении, обращая особое внимание на случаи повторного создания идентичных ресурсов и избавляясь от подобной избыточности в коде. Если в вашем приложении непрерывно выполняются операции рисования, то такие объекты, как шрифты, перья, кисти и маски прозрачности, должны либо однажды распределяться в цикле рисования, либо глобально кэшироваться.