Утечка памяти в WPF RichTextBox - PullRequest
       14

Утечка памяти в WPF RichTextBox

5 голосов
/ 26 октября 2009

В моем приложении у меня есть много RichTextBox, которые создаются динамически во время выполнения. Я понял, что у приложения есть утечка памяти, которая вызвана элементами управления RichTextBox. Чтобы доказать утечку памяти из-за контроля, я написал следующий метод теста:

for (int i = 0; i < 3000; i++)
        {
            Control rich = new RichTextBox();
            pnl.Content = rich;
        }
GC.Collect();
GC.WaitForPendingFinalizers();

pnl - это ContentControl, который объявлен в коде Xaml.
Если вы запустите следующий код, вы увидите, что использование памяти быстро растет.

Есть идеи как решить проблему? Я подумал о создании пула объектов, но это усложнило бы мое приложение, и я бы предпочел его избегать.


edit : я добавил вызов сборщику мусора, чтобы продемонстрировать, что объекты не являются сборщиком мусора - нет улучшения в использовании памяти с вызовом метода GC и без него. Обратите внимание, что вызов rich.Dispose в цикле устраняет рост использования памяти.

Ответы [ 5 ]

8 голосов
/ 26 октября 2009

Это не признак того, что ваше приложение имеет утечку памяти, это признак того, что ваше приложение использует много памяти . Утечка, если RichTextBox элементы управления не освобождаются в какой-то момент после того, как они выпали из области видимости (обнаружение утечек памяти на управляемых объектах, как известно, сложно и недоказуемо).

Распространенное заблуждение, что объект, выпадающий из области видимости, вызовет его сборку мусора. Это просто делает приемлемым для сбора. Теоретически объект никогда не может быть собран до завершения приложения. Тот факт, что он увеличивается с RichTextBox, а не с другими элементами управления, не означает, что в RichTextBox имеется утечка памяти, это просто означает, что он использует больше памяти на экземпляр, чем другие элементы управления. Хотя эта информация может быть полезной, она не помогает при определении наличия утечки памяти.

2 голосов
/ 09 декабря 2009

Нашел это в другом месте, и, похоже, это правильно в отношении моего тестирования.

Когда создается FlowDocument, относительно дорогое форматирование объекты контекста также создаются для это в его StructuralCache. Когда ты создать несколько FlowDocs в тесном цикл, StructuralCache создается для каждый FlowDoc. Давай ты позвонил Gc.Collect в конце цикла, в надежде восстановить память. StructuralCache имеет финализатор освобождает этот контекст форматирования, но не сразу. Финализатор эффективно планирует операцию освободить контексты в DispatcherPriority.Background.

Таким образом, RichTextBox (или FlowDocument) на случай не протекает, просто ожидая очистки в фоновом потоке. Когда он запускается точно, кто знает. Хотелось бы, чтобы это только что реализовало метод dispose, который немедленно вызвал бы очистку.

1 голос
/ 23 сентября 2011

Это исправило проблему для меня: http://blingcode.blogspot.com/2010/10/memory-leak-with-wpfs-richtextbox.html

В основном добавьте два атрибута к каждому RichTextBox :) :) IsUndoEnabled = "False"

1 голос
/ 26 октября 2009

У нас была та же проблема в winforms 2.0, и нам пришлось купить сторонний форматированный текстовый элемент управления. Я думаю, что Microsoft не удосужилась исправить это ...

0 голосов
/ 26 октября 2009

Относительно вашего редактирования:

Вы добавили вызовы GC после , цикл завершается, и все 3000 RichTextBox ов созданы.

Хотя я согласен с тем, что кажется странным, что предыдущий не освобождается в цикле, когда он заменяется новым, это настолько узкий цикл, что GC, вероятно, не получает шанса «сделать это» до завершения цикла.

Не думаю, что это хорошая идея (но в тестовом коде все должно быть в порядке), но вы пытались переместить вызовы GC внутри цикла?

...