Как управлять COM-объектами в .Net веб-приложении - PullRequest
0 голосов
/ 24 февраля 2009

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

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

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

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

Ответы [ 2 ]

1 голос
/ 26 февраля 2009

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

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

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

System.Runtime.InteropServices.Marshal.ReleaseComObject

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

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

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

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

0 голосов
/ 26 февраля 2009

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

...