Ситуация
Мы запускаем большое приложение WPF, которое не выпускает память в течение некоторого времени. Это не настоящая утечка памяти, так как память скоро будет выпущена. Я знаю, что это нормально, это не будет рассматриваться как проблема. К сожалению, это становится проблемой производительности вместе с инфраструктурой управления WPF. Подробнее см. Ниже.
Выводы
У нас есть автоматические тесты, которые выполняют типичные варианты использования. Некоторые случаи работают нормально и освобождают память во времени. Другие блокируют память до тех пор, пока клиент не будет сведен к минимуму, не откроется новое окно или не появятся другие условия, которые запускают коллекцию Gen2.
• С ANTS мы видим, что объекты не имеют GC Root, но много ссылок на другие объекты, которые требуют завершения.
• WinDbg не показывает, какие объекты будут готовы для завершения.
• Запуск нескольких GC.Collect()
, GC.WaitForPendingFinalizers()
полностью освобождает память.
• Мы знаем, какое действие UI вызывает высокое состояние памяти, но мы не смогли идентифицировать какой-либо подозрительный код.
Вопрос
Мы будем признательны за любые советы по отладке такой проблемы.
Фон > CommandManager WPF
Командный менеджер WPF содержит частную коллекцию WeakReferences (_requerySuggestedHandlers
) для создания события CanExecuteChanged
. Обработка CanExecuteChanged
довольно дорогостоящая (особенно нахождение EventRoute для CanExecute
, которое, по-видимому, является RoutedEvent
). В любое время, когда CommandManager чувствует себя готовым к выполнению команд, он выполняет итерацию через эту коллекцию и вызывает событие CanExecuteChanged
в соответствующих источниках команд.
The WeakReferences не удаляются из этой коллекции, пока есть дескриптор GC для указанного объекта. Хотя объект не был собран, CommandHelper продолжает обрабатывать события CanExecute
для этих элементов (ButtonBase или MenuItems). В случае, если много мусора (как в нашем случае), это может привести к чрезвычайно большому количеству вызовов обработчиков событий CanExecute, что приводит к тому, что приложение действительно отстает.