WeakReferences не освобождаются во встроенной ОС
У меня странное поведение:
Я получаю массивную утечку памяти при создании приложения WPF, которое работает на DLOG-терминале (Windows Embedded Standard SP1), который ведет себя отлично, если я запускаю его локально на обычном рабочем столе (Win7 prof.)
После многих неудачных попыток найти какую-либо проблему я поставил одну из них непосредственно рядом с моим монитором, установил ANTs MemoryProfiler и проработал один час тестового запуска, имитирующего пользовательские операции как на терминале, так и на моем компьютере разработки.
Результат состоит в том, что из-за некоторых странных причин встроенная система накапливает огромное количество объектов WeakReference и EffectiveValueEntry [].
Вот некоторые фотографии:
Разработка (ПК):
![enter image description here]()
![enter image description here]()
И терминал:
![enter image description here]()
Просто взгляните на список классов...
![enter image description here]()
Кто-нибудь видел что-то подобное раньше и есть ли известные решения?
Где я могу получить помощь?
(PS терминалы, где установлены изображения, подготовленные для .net4)
PPS: для близкого избирателя: я думаю, вопрос ясен: как я могу это исправить.
Вы можете утверждать, что это проблема IT/OS и проблема программирования, но я думаю, что если я опубликую это в Ошибка сервера, она мгновенно закрывается вне темы...
UPDATE:
Мне удалось найти большую часть проблемы, но она немного похожа на С++:
Я использую класс элементов, похожий на ViewModel, для WPF-List, который предоставляет (среди прочих) ICommand (RelayCommand-pattern). Элементы, созданные на ходу в getter ViewModel-Property для представления, и кажется, что приложение /GC никогда не освобождало эти неиспользуемые команды - или подписки на их CanExecuteChanged - профайлер памяти показывает те, что "удерживаются слабая ссылка". Я изменил свой код для повторного использования этих моделей-элементов и Dispose/set для нулевого использования всех используемых свойств в их Dispose и использования этого также как очистка - как я уже сказал: чувствует себя как "удалить" в те старые дни С++.
Вдобавок к этому я использую принудительный GC.Collect каждые 30 минут (да, я знаю - вы никогда не должны, но до сих пор у меня нет другого решения).
С этой установкой приложения работают до 6 часов без проблем, но это не кажется правильным.
Я не могу понять, почему эти WeakReferences не востребованы, поскольку они находятся на моей настольной машине...
Любые мысли об этом? Пожалуйста!
UPDATE:
Я все еще не в состоянии решить эту проблему, но вижу странное поведение:
Если я использую PC-Anywhere для наблюдения за работой моего программного обеспечения на одном из терминалов, проблема исчезнет!
Даже после запуска 8 часов. прямое программное обеспечение работает так, как должно - оно будет даже освобождать память (я помещаю небольшое отображение памяти на главный экран - скажем, я подключаюсь к терминалу и вижу, что память низкая - после ожидания нескольких минут память восстанавливается )
Итак, я думаю, что Devin (один ответ ниже) имеет преимущество в правильном направлении - что-то в программном обеспечении Remote-Control разблокирует поток финализатора или что-то, что блокирует GC - будь то симулированная клавиатура/мышь или что-то еще.
Любые мысли об этом?
Ответы
Ответ 1
У нас была (несколько) аналогичная проблема с моим приложением на планшете. Память будет исправлена при запуске на рабочем столе, но не при запуске на планшете или другом устройстве, использующем панель ввода ПК. Проблема в том, что очередь финализации застревает. Финализатор COM-объектов ожидал выполнения чего-то в основном потоке, у которого не было цикла сообщений.
Решение заключалось в том, чтобы найти подходящее время для вызова Application.DoEvents()
. У нас был метод, который будет называться прерывисто, и мы вызываем его с каждым 10-м звонком. Я не знаю, есть ли у вас такая же проблема, но, возможно, она может пролить свет.
РЕДАКТИРОВАТЬ: Мне нужно четко прояснить, что вызов DoEvents()
- плохая идея. Он работает в этом случае, потому что в этом потоке нет никакого пользовательского интерфейса или что-либо еще, что может повлиять на эти события.
Ответ 2
Из скриншотов интересно видеть, что LOH растет одновременно с тем, что используемое пространство не сильно растет. Свободное пространство растет на LOH, что указывает на фрагментацию памяти из-за закрепленных объектов. Это похоже на застрявший поток финализатора, который предотвращает очистку управляемых объектов. Вы должны получить дамп памяти и проверить, в каком методе застряла нить финализатора. Вы можете сделать это довольно легко с помощью Windbg.