Утечка памяти в WPF - PullRequest
4 голосов
/ 19 мая 2010

У меня есть форма WPF, которую я сам не создал, поэтому я не очень хорош в WPF. Тем не менее, он протекает плохо, до 400 МБ и закрытие формы не помогает.

Проблема заключается в том, что мое приложение загружает все картинки одновременно. Я хотел бы загрузить только те, которые видны в данный момент. Это около 300 изображений, и они немного большие, поэтому моя WPF-форма страдает от загрузки их всех.

У меня есть DataTemplate с моим собственным типом, у которого есть свойство Thumbnail. Код в шаблоне выглядит так:

            <Image Source="{Binding Path=Thumbnail}" Stretch="Fill"/>

И тогда у меня есть сетка с элементом управления, который имеет выше шаблон в качестве источника. Код для этого элемента управления приведен ниже. Пожалуйста, дайте мне советы о том, как оптимизировать код и, возможно, получить только те, которые видны и имеют только столько загруженных элементов управления одновременно?

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Controls:ElementFlow">
                <Grid Background="{TemplateBinding Background}">
                    <Canvas x:Name="PART_HiddenPanel"
                            IsItemsHost="True"
                            Visibility="Hidden" />
                    <Viewport3D x:Name="PART_Viewport">
                        <!-- Camera -->
                        <Viewport3D.Camera>
                            <PerspectiveCamera FieldOfView="60"
                                               Position="0,1,4"
                                               LookDirection="0,-1,-4"
                                               UpDirection="0,1,0" />
                        </Viewport3D.Camera>

                        <ContainerUIElement3D x:Name="PART_ModelContainer" />

                        <ModelVisual3D>
                            <ModelVisual3D.Content>
                                <AmbientLight Color="White" />
                            </ModelVisual3D.Content>
                        </ModelVisual3D>
                <Viewport2DVisual3D
        RenderOptions.CachingHint="Cache"
        RenderOptions.CacheInvalidationThresholdMaximum="2"
        RenderOptions.CacheInvalidationThresholdMinimum="0.5"/>
                    </Viewport3D>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Ответы [ 3 ]

4 голосов
/ 19 мая 2010

Первое, на что нужно обратить внимание, когда вы пытаетесь обнаружить утечки памяти в приложении .NET, WPF или нет, это объекты, которые подписываются на события.

Если объект X прослушивает событие, вызванное объектом Y, тогда Y содержит ссылку на X. Какой бы метод виртуализации (или удаления) вы ни внедрили, если X не отписывается от события Y, X останется в объекте График, пока Y делает, и никогда не будет завершен и сборщик мусора. (Даже если он реализует IDisposable и вы явно вызываете Dispose для него.)

Когда вы говорите «закрытие формы не помогает», это вызывает у меня двойное подозрение: я ожидаю, что кто-то реализовал свойство объекта для объекта Window, и этот объект подписался на какое-то событие. Таким образом, вы закрываете окно, но оно все еще существует в графе объектов, поскольку на одно из его свойств ссылаются.

(Чтобы дать вам представление о том, насколько коварным это может быть: элементы управления WinForms ToolStrip подписываются на события изменения темы Windows, когда они становятся видимыми. Это замечательно, потому что изменение темы вашего компьютера автоматически отражается в пользовательском интерфейсе вашего Запуск приложения. Это не так здорово, если вы разыменуете ToolStrip без предварительной установки Visible в false, оно будет продолжать получать события смены темы, пока приложение не завершится.)

Профилировщик памяти может помочь с этим - вот как я обнаружил, что мое приложение имеет в памяти тысячи ToolStrip объектов, хотя я думал, что все они были уничтожены.

2 голосов
/ 19 мая 2010

Является ли элемент управления ElementFlow тем же, который описан здесь ? Похоже, что элемент управления уже использует виртуализацию , поэтому я не ожидаю, что он получит доступ к свойству Thumbnail невидимого элемента.

Как вы моделируете структуру данных, которая предоставляет свойство 'Thumbnail'? Можете ли вы настроить его так, чтобы свойство request загружало миниатюру при первом доступе? Возможно, реализация этого с помощью резервного кэша (который хранит миниатюры, загруженные в течение определенного периода времени) решит проблему.

EDIT

Возможно, я предположил что-то, чего не должен был иметь. Читая комментарии ко второму сообщению, которое я связал, я теперь думаю, что, возможно, общедоступная версия элемента управления ElementFlow фактически не реализует виртуализацию. Возможно, вы могли бы зарегистрировать доступ к свойству «Миниатюра» и определить, доступно ли свойство для невидимых элементов.

0 голосов
/ 19 мая 2010

Трудно сузить проблему, используя только ваш фрагмент кода. Возможно, вы захотите Visual Profiler , если вы еще этого не сделали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...