Чтение онлайн

ЖАНРЫ

Программирование мобильных устройств на платформе .NET Compact Framework

Салмре Иво

Шрифт:

Приведенный в листинге 8.1 пример кода иллюстрирует два способа отложенного создания и кэширования глобально используемых графических ресурсов. Существует два способа создания объектов:

1. Пакетное создание групповых ресурсов. Приведенный ниже код создает списочный массив, содержащий четыре растровых изображения. Эти изображения являются кадрами анимации, поэтому они загружаются все вместе и помещаются в индексированный массив, откуда их можно легко извлекать. Программный код, которому требуется доступ к этой коллекции изображений, должен использовать вызов GraphicsGlobals.PlayerBitmapsCollection;. Если массив изображений уже загружен в память, функция незамедлительно возвращает кэшированный объект. В противном случае отдельные

ресурсы изображений сначала загружаются в массив и лишь затем возвращаются. Если приложение переходит в состояние, в котором пребывание изображений в памяти не требуются, код приложения может выполнить вызов GraphicsGlobals.g_PlayerBitmapsCollection_CleanUp;, в результате чего произойдет освобождение растровых ресурсов и массива. Системные ресурсы, задействованные для обслуживания растровых изображений, будут немедленно освобождены, а управляемая память, которую занимали эти объекты, будет соответствующим образом восстановлена в процессе сборки мусора.

2. Индивидуальное создание графических ресурсов. В случае ресурсов, которые не должны обязательно использоваться вместе, как в приведенном выше примере, часто оказывается удобным создать функцию кэшированного доступа, посредством которой и реализуется управление доступом к ресурсу. Когда происходит первое обращение к этой функции с запросом ресурса (например, GraphicsGlobals.g_GetBlackPen;), она создает его экземпляр. В случае часто используемых ресурсов такой подход оказывается намного более эффективным, чем постоянное создание и уничтожение экземпляров ресурса всякий раз, когда он требуется для выполнения того или иного фрагмента кода. Создавая приведенный ниже код, я допустил, что все ресурсы должны освобождаться одновременно, и написал функцию (GraphicsGlobals.g_CleanUpDrawingResources;), которая освобождает все кэшированные ресурсы, которые были созданы. Эта функция должна вызываться тогда, когда приложение переходит в состояние, в котором эти ресурсы не требуются.

Используя кэширование, руководствуйтесь здравым смыслом

Если предполагается многократное использование одних и тех же ресурсов внутри функции, то вызов функции (или свойства) кэшированного доступа всякий раз, когда требуется данный ресурс, является неэффективным. В подобных случаях лучше вызвать эту функцию один раз и хранить ресурс в локальной переменной в течение всего времени, пока в данном ресурсе будет существовать необходимость. Тем самым вы получаете выигрыш от того, что используете глобально кэшированный ресурс, а не создаете и уничтожаете ресурс внутри функции, и повышаете эффективность вычислений, поскольку избавляетесь от лишних вызовов функции в своем алгоритме. Здравый смысл подскажет вам, когда такой подход является оправданным.

Листинг 8.1. Применение отложенной загрузки, кэширования и освобождения графических ресурсов 

using system;

public class GraphicsGlobals {

 private static System.Drawing.Bitmap s_Player_Bitmap1;

 private static System.Drawing.Bitmap s_Player_Bitmap2;

 private static System.Drawing.Bitmap s_Player_Bitmap3;

 private static System.Drawing.Bitmap s_Player_Bitmap4;

 private static System.Collections.ArrayList s_colPlayerBitmaps;

 //------------------------------------------------------

 //Освободить все ресурсы

 //------------------------------------------------------

 public static void g_PlayerBitmapsCollection_CleanUp {

//Если не загружено ни одно изображение, то и память освобождать не от чего

if (s_colPlayerBitmaps == null) {

return;

}

//Дать
указание каждому из этих объектов освободить

//любые удерживаемые ими неуправляемые ресурсы

s_Player_Bitmap1.Dispose;

s_Player_Bitmap2.Dispose;

s_Player_Bitmap3.Dispose;

s_Player_Bitmap4.Dispose;

//Обнулить каждую из этих переменных, чтобы им не соответствовали

//никакие объекты в памяти

s_Player_Bitmap1 = null;

s_Player_Bitmap2 = null;

s_Player_Bitmap3 = null;

s_Player_Bitmap4 = null;

//Избавиться от массива

s_colPlayerBitmaps = null;

 }

 //Функция: возвращает коллекцию изображений

 public static System.Collections.ArrayList g_PlayerBitmapsCollection {

//---------------------------------------------------------------

//Если изображения уже загружены, их достаточно только возвратить

//---------------------------------------------------------------

if (s_colPlayerBitmaps != null) {

return s_colPlayerBitmaps;

}

//Загрузить изображения как ресурсы из исполняемого двоичного файла

System.Reflection.Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly;

System.Reflection.AssemblyName thisAssemblyName = thisAssembly.GetName;

string assemblyName = thisAssemblyName.Name;

//Загрузить изображения

s_Player_Bitmap1 = new System.Drawing.Bitmap(

thisAssembly.GetManifestResourceStream(assemblyName + ".Hank_RightRun1.bmp"));

s_Player_Bitmap2 = new System.Drawing.Bitmap(

thisAssembly.GetManifestResourceStream(assemblyName + ".Hank RightRun2.bmp"));

s_Player_Bitmap3 = new System.Drawing.Bitmap(

thisAssembly.GetManifestResourceStream(assemblyName + ".Hank_LeftRun1.bmp"));

s_Player_Bitmap4 = new System.Drawing.Bitmap(

thisAssembly.GetManifestResourceStream(assemblyName + ".Hank_LeftRun2.bmp"));

//Добавить изображения в коллекцию

s_colPlayerBitmaps = new System.Collections.ArrayList;

s_colPlayerBitmaps.Add(s_Player_Bitmap1);

s_colPlayerBitmaps.Add(s_Player_Bitmap2);

s_colPlayerBitmaps.Add(s_Player_Bitmap3);

s_colPlayerBitmaps.Add(s_Player_Bitmap4);

 //Возвратить коллекцию

 return s_colPlayerBitmaps;

 }

 private static System.Drawing.Pen s_blackPen;

 private static System.Drawing.Pen s_whitePen;

 private static System.Drawing.Imaging.ImageAttributes s_ImageAttribute;

Поделиться с друзьями: