Прежде всего вам нужно понять, что то, что вы делаете, довольно странно!
«Нормальный» способ загрузки текстуры - использование конвейера контента и менеджера контента.
Если вам действительно нужно загрузить текстуру из файла, а не из системы содержимого - вы должны сделать это только один раз для каждой текстуры. Вы должны использовать Texture2D.FromFile
в Game.LoadContent
и вызывать Dispose
в Game.UnloadContent
(обычно менеджер контента обрабатывает вызов Dispose для вас - но поскольку вы не проходите через менеджер контента, вы должны позвонить в Dispose самостоятельно) .
Важно понимать, что вы работаете как с управляемыми, так и с неуправляемыми ресурсами.
Память, используемая управляемыми объектами, будет обрабатываться сборщиком мусора - в этом случае каждый экземпляр Texture2D использует крошечный бит управляемой памяти. 99% времени вам не нужно беспокоиться об этом - сборщик мусора действительно хорош в обработке управляемой памяти - это его работа!
Что вам нужно беспокоить, так это неуправляемые ресурсы - в этом случае память текстур используется всеми этими текстурами, которые вы загружаете. В конечном итоге запустится сборщик мусора, увидит все эти не связанные объекты Texture2D и соберет их. Когда он собирает их, он завершает их, что, как и вызов Dispose, освобождает неуправляемые ресурсы.
Но сборщик мусора не может "видеть" все неуправляемые ресурсы, которые используют эти объекты Texture2D. Он не знает, когда эти объекты должны быть выпущены - вы можете сделать намного лучшую работу самостоятельно. Все, что вам нужно сделать, это вызвать Dispose
для ваших текстур, когда они больше не нужны.
Это потому, что сборщик мусора не знает об этих 30 МБ дополнительной памяти, используемой вашими текстурами, что она накапливается, когда вы не вызываете Dispose. В дополнение к этому, когда вы смотрите на использование памяти процесса, вы не можете видеть всю память графического процессора, которую используют эти текстуры!
(Базовая реализация Texture2D состоит в том, что она содержит ссылку на объект текстуры DirectX - который сам по себе является неуправляемым объектом, использующим неуправляемую основную память - который, в свою очередь, обрабатывает текстуру и связанную с ней память в графическом процессоре. Управляемая часть объект Texture2D имеет размер около 100-200 байт, в котором хранится вышеупомянутая ссылка и кэш с шириной, высотой, форматом текстуры и т. д.)
Теперь - о том, чего вы пытаетесь достичь. Если у вас действительно есть необходимость загружать текстуру каждый кадр (это весьма необычно), и вам также больше не нужна предыдущая текстура ...
Ну, во-первых, вызов Dispose
для неиспользуемой текстуры каждый кадр является допустимым методом. Вы будете зависеть от сборщика мусора для очистки всего создаваемого мусора (управляемая сторона объектов Texture2D) - это хорошо для Windows, но может снизить производительность на Xbox. По крайней мере, вы не будете пропускать неуправляемые ресурсы.
Лучший способ, особенно если текстура каждый раз одного и того же размера, это просто продолжать использовать один и тот же объект текстуры. Затем назовите Texture2D.SetData
для него с новыми данными текстуры в каждом кадре.
(Если ваши текстуры имеют разные размеры, или если вы используете более одной текстуры в данный момент времени, вам может потребоваться реализовать что-то вроде пула текстур.)
Конечно, LoadFile принимает фактический файл, SetData принимает необработанные данные. Вы должны будете выполнить преобразование данных самостоятельно. Хорошей отправной точкой может быть эта тема на форуме XNA .