Фон для моего вопроса таков: я конвертирую приложение для обработки сообщений, которое использует множество компонентов COM из VB6 в C #.Многие из компонентов COM в приложении являются детализированными компонентами, которые используются в больших количествах и с частотой в циклах обработки сообщений.Я наблюдаю значительное (и прогрессивно растущее) увеличение использования памяти при обработке набора тестовых сообщений в приложении C # по сравнению с приложением VB6.Я использовал профилировщик памяти в приложении, которое подтвердило, что высокое использование памяти было вызвано живыми экземплярами COM-объектов в неуправляемой куче приложения.Я знаю, что эти компоненты не «просочились» из-за живых ссылок, потому что если я положу GC.Collect () в ядро цикла обработки сообщений, использование памяти будет плоским и почти идентичным приложению VB6 (хотя производительностьужасно ухудшается, как и следовало ожидать).
Я прочитал все, что могу найти на сборщике мусора нескольких поколений в C #, вызываемых оболочках во время выполнения, неуправляемом распределении памяти ресурсов, Marshal.ReleaseComObject (), Marshal.FinalReleaseComObject () и т. д. Ничто из этого не объясняет, почему приложение удерживает работающие COM-объекты в неуправляемой куче, когда соответствующие RCW имеют право на сборку мусора.
В некоторых статьях я видел намеки на возможность того, что фактическая реализация сборщика мусора в C # может включать в себя оптимизации, такие как не выполнение сбора всех подходящих объектов в конкретном поколении.Если бы это или что-то подобное было правдой, это могло бы объяснить, почему подходящие RCW и их соответствующие COM-объекты не собираются и уничтожаются.Другое объяснение может быть, если уничтожение COM-объекта в неуправляемой куче не связано напрямую с коллекцией соответствующих RCW.Я не нашел ничего такого, что предлагало бы такую степень детализации обработки COM-объектов в .NET.Мне нужно понять это лучше, потому что использование памяти моего приложения в настоящее время недопустимо.Любые указатели или рекомендации будут с благодарностью.
Редактировать: Я должен добавить, что я довольно хорошо знаком с финализаторами (которые не описаны в существующем на RCW) и интерфейсом IDisposable (который RCWsне реализовывать).Насколько я понимаю, Marshal.ReleaseComObject () - это правильный метод явного «удаления» ссылки COM.Я был осторожен, чтобы добавить это утверждение для каждого известного использования COM-объекта в моем приложении, и это не привело к разнице в использовании памяти.
Кроме того, неясно, почему отсутствие кода удаления или завершения может быть проблемой, если добавление явного GC.Collect () не приводит к проблемам с памятью.Ни Dispose (), ни наличие финализатора не приводят к фактической коллекции объектов.Первый позволяет объекту подавить свой этап завершения (если таковой имеется), а второй позволяет очистить неуправляемые ресурсы, ни один из которых не выставлен в RCW.