Чрезмерное использование памяти в C # с большим количеством COM-объектов - PullRequest
2 голосов
/ 15 марта 2011

У меня есть приложение, которое было изначально написано на VB6, и я использовал инструмент для преобразования в C # с довольно хорошим успехом с функциональной точки зрения.Он обрабатывает большое количество сообщений, используя множество объектов COM (C ++) малого и среднего размера.

Я заметил, что конкретный тестовый запуск в старом приложении VB6, который выполнялся с использованием менее 40 МБ памяти, требовал около 900 МБ в приложении C #.Если я помещу GC.Collect () в самый внутренний цикл обработки сообщений приложения C #, он использует ту же или меньшую память, что и приложение VB6, хотя тогда это действительно очень медленно.Это заставляет меня поверить, что в абсолютном смысле слова «утечки» нет.

Затем я запустил приложение C # через профилировщик памяти AQTime и сообщил, что было слишком много объектов COM / C ++.жить в куче.Я предположил, что это произошло потому, что вызываемые оболочки во время выполнения вокруг COM-объектов были довольно малы и никогда (или редко) не запускали коллекцию в C #, даже если их COM-объекты, на которые они ссылаются, были значительно больше.Я думал, что смогу решить эту проблему, добавив явные вызовы Marshal.ReleaseComObject () вокруг объектов COM в приложении C #.Я пошел и сделал это во многих местах, где время жизни объектов COM было легко определить.Я заметил только очень небольшое сокращение использования памяти.

Мне интересно, почему у меня не было большего успеха с этим.Просматривая статические методы в классе Marshal, я вижу некоторые, которые наводят меня на мысль, что либо я упускаю некоторую тонкость в обработке ссылок COM, либо мое предположение, что они немедленно уничтожаются, когда счетчик ссылок RCW достигает нуля, неверно.

Буду признателен за любые предложения о других подходах, которые я мог бы попробовать, или о других вещах, которые я мог упустить из виду или неправильно.

1 Ответ

3 голосов
/ 15 марта 2011

Извините за ссылку, а не за хороший синопсис, но у меня никогда не было этой проблемы, поскольку я имел дело с IE и mshtml в долгоживущем сценарии.

В статье говорится:

При использовании COM-объекта из приложения на основе .NET участвуют два объекта: RCW и COM-объект (или объекты).Сборщик мусора знает только о размере RCW (который может быть небольшим), но не о COM-объекте (который может быть большим).Поэтому, хотя приложение на основе .NET может освобождать RCW, сборщик мусора может не восстанавливать RCW, даже если память заканчивается.Пока RCW остается в памяти, управляемый им COM-объект также остается в памяти.

Существует два механизма, которые обеспечивают освобождение COM-объектов из памяти: объект AppDomain и метод ReleaseComObject.Использование AppDomain обеспечивает простейшее решение для управления COM-объектами, но снижает производительность и может создавать угрозу безопасности.Использование ReleaseComObject позволяет избежать этих затрат, но требует более тщательного планирования и кодирования.

...