Почему мое приложение WPF UniformGrid зависает при связывании и использует большие объемы памяти? - PullRequest
0 голосов
/ 04 января 2019

Используя C # WPF, я разрабатываю средство просмотра плитки для 2D-игры с игровой сеткой не более 255x255 плиток. Каждая плитка может содержать до 4 оверлейных изображений, которые имеют размер 100x100px .PNG и используют прозрачность. Каждый рисунок имеет размер около 1 КБ.

Моя цель - создать вьюер карт для просмотра карты этих тайлов. Любая данная карта будет иметь размер не более 255x255.

Я хотел сделать это в WPF C #, чтобы воспользоваться преимуществами быстрой разработки, которая идет вместе с ItemsCollections, и полагал, что UniformGrid будет идеальным элементом управления для отображения моей графики и данных плитки.

Настройка программы:

Мой ItemsControl привязан к ItemSource, который является списком класса 'Tile', который я создал. Класс My Tile содержит различные данные о плитке и содержит 4 переменные BitmapImage, которые содержат изображения из нескольких слоев, которые будут отображаться в этой плитке.

Мой шаблон ItemsControl выглядит примерно так, просто чтобы дать представление о структуре:

<ItemsControl ItemSource={Binding MapTiles}>
    <ItemSControl.CacheMode>
        <BitmapCache/>
    </ItemsControl.CacheMode>
    <ItemControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="{Binding MapInfo.width}" Columns="{Binding MapInfo.height}">
        </ItemsPanelTemplate>
    </ItemControl.ItemsPanel>
    <Grid>
        <Image Source={Binding image1graphic}>
        <Image Source={Binding image2graphic}>
        <Image Source={Binding image3graphic}>
        <Image Source={Binding image4graphic}>
    </Grid>
</ItemsControl>

На данный момент я могу успешно загрузить карту тайлов размером 100x100 после долгого ожидания, и мое приложение перестало отвечать на запросы в течение минуты (подробности см. Ниже). После того, как все загружено, программа работает отлично и отзывчиво, однако на больших картах возникают проблемы (см. Ниже)

Вот проблемы с этим подходом, которые, я надеюсь, кто-то может мне помочь ..

Выпуск № 1:

Когда я заполняю свой список MapTiles 100x100, окно приложения будет буквально зависать на одну минуту, пока происходит процесс привязки. Я провел много исследований и не могу понять, как заставить приложение выполнять процесс привязки в фоновом потоке. Похоже, оно выполняет эту операцию массового связывания только в основном потоке графического интерфейса.

Хотя приложение заморожено во время процесса привязки данных, отладчик показывает огромное количество операций по сбору мусора, выполняемых при увеличении использования памяти до 1 ГБ

enter image description here

Когда я пытаюсь увеличить размер до 200x200, у меня возникают проблемы с производительностью и памятью. Процесс привязки данных приводит к тому, что приложение перестает отвечать на запросы в течение до 3 минут, что приводит к взаимоблокировке переключателя контекста в отладчике, и использование памяти иногда достигает 4 ГБ в 32-разрядном режиме и до 8 ГБ в 64-разрядном режиме ( это кажется крайним)

Я позаботился о том, чтобы заморозить все мои BitmapImages после назначения их моему классу плиток, чтобы уменьшить время рендеринга и повысить производительность.

Приложение перестает отвечать на запросы и длительное время привязки данных (1+ минут) является ограничением WPF или, возможно, UniformGrid?

Возможно, есть лучший способ сделать это?

Выпуск № 2:

Хотя мои изображения имеют размер всего 1 КБ, с размером сетки 100x100, что составляет 10 000 плиток, причем каждая плитка содержит до 4 растровых изображений, я предполагаю, что для кэширования потребуется менее 100 МБ памяти. мое приложение использует около 2 ГБ памяти при работе в 32-разрядном режиме и более 6 ГБ памяти при работе в 64-разрядном режиме.

Это нормально? Я знаю, что использование памяти WPF отличается от традиционных приложений Windows Forms, однако я не уверен, почему используется такой большой объем памяти.

Возможно, это как-то связано с тем, как кэширование и привязки данных работают в моей настройке? Любая помощь будет оценена

1 Ответ

0 голосов
/ 04 января 2019

Вы не сможете иметь такое большое визуальное дерево. Это просто не выполнимо. Вы можете либо переопределить OnRender () и сделать рисование самостоятельно, либо попробовать виртуальную панель: https://www.codeproject.com/Articles/158060/Dan-Crevier-s-VirtualizingTilePanel-Mod.

...