Как управлять COM-объектами в веб-приложении .Net

Устаревшие приложения C++ с иногда печально известными проблемами утечки памяти должны вызываться из приложения Windows на базе сервера .Net. Время сборки мусора .Net невозможно определить, и иногда объект С++ уничтожается или не уничтожается «вовремя», что приводит к непредсказуемым результатам и, как правило, к сбою веб-приложения С#. Каков наилучший способ помещать объекты С++ в стек сборки мусора как можно чаще, но не так часто, чтобы удалить ссылку .Net на объект COM. Имейте в виду, что COM-объекты могут порождать подобъекты, поэтому счетчик ссылок .Net на COM-объекты может изменяться только вызовом функции, а не обязательно созданием экземпляра.

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

Мне пришлось решить эту проблему с помощью .Net 1.1 пару лет назад. Интересно, было ли у кого-то еще мое решение или лучшее. Это НЕ ASP.NET. Это .Net DLL.

Окончательный результат не был полностью удовлетворительным, и каждые несколько месяцев веб-сервер давал сбой.


person ssorrrell    schedule 24.02.2009    source источник
comment
Я склонен согласиться с тем, что с .Net 1.1 это сложно или невозможно, но у нас есть возможность перейти на .Net 2.0. Это по своей сути лучше или в нем есть новые функции, которые могли бы помочь?   -  person ssorrrell    schedule 26.02.2009


Ответы (2)


Вы спрашиваете: «Как лучше всего помещать объекты С++ в стек сборки мусора как можно чаще», но объекты С++ никогда не удаляются сборщиком мусора. Может быть, посмотреть на это так...

У вас есть процесс, который создает несколько объектов C++. Некоторые из этих объектов C++ реализуют COM-объекты, поэтому их время жизни управляется через AddRef/Release. Некоторые из этих COM-объектов импортируются в мир .NET и упаковываются с помощью RCW (оболочки, вызываемой во время выполнения). Только RCW является объектом .NET и попадает в кучу со сборкой мусора.

Без какого-либо вмешательства с вашей стороны RCW в конечном итоге будет подвергнут сборке мусора, и когда это произойдет, он выполнит Release для своего базового COM-объекта. Если вы хотите немедленно освободить COM-объект, не дожидаясь сборки мусора, вы можете вызвать...

System.Runtime.InteropServices.Marshal.ReleaseComObject

... или даже FinalReleaseComObject, если вы уверены, что это то, что вам нужно.

Чтобы вернуться к вашему вопросу: вы хотите знать, как удалить объекты С++, не освобождая ссылку .NET на ваш COM-объект. Поскольку объекты C++ не существуют в куче .NET, нет никакого способа добиться этого напрямую. Вы можете предоставить метод из вашего COM-объекта, который удаляет все его объекты C++, и просто вызвать его из вашего кода .NET. Но я предполагаю, что если бы ваш COM-объект мог идентифицировать все просочившиеся объекты С++, вы бы уже это сделали.

Надеюсь, я объяснил, почему нет способа добиться того, что вы предлагаете в своем вопросе, но есть множество инструментов, которые помогут вам найти и исправить утечки памяти. Я предлагаю использовать такой инструмент, как LeakDiag (поищите его в StackOverflow), чтобы выяснить, где в вашем коде на С++ происходит утечка памяти.

Прагматичное решение, если вы используете IIS6 или более позднюю версию, — настроить повторное использование пула приложений. Вы можете настроить числа так, чтобы процессы завершались и перезапускались до того, как они когда-либо утекли достаточно памяти, чтобы вызвать проблемы, и обычно это работает таким образом, что пользователи не замечают никаких простоев.

person Martin    schedule 26.02.2009

Создайте приложение COM+ и поместите в него используемые вами классы COM. Таким образом, все COM-объекты создаются в отдельном процессе. Вы можете периодически освобождать все COM-объекты и просто перезапускать процесс приложения COM+.

person sharptooth    schedule 26.02.2009
comment
Сохранение COM-объектов в отдельном процессе — интересная идея. Я не уверен, что это возможно. - person ssorrrell; 26.02.2009
comment
Вот как работает COM+. Вы берете внутрипроцессный COM-сервер и просите COM+ создать приложение COM+, которое на самом деле представляет собой внепроцессный COM+-сервер с той же функциональностью. А внепроцессный означает, что все объекты находятся в отдельном процессе. - person sharptooth; 27.02.2009