Утечки памяти в многопоточном приложении с использованием COM и C #

Я написал многопоточное неуправляемое приложение, которое использует COM-объекты в своих рабочих потоках. Все шло нормально, пока я не начал использовать для работы объекты .NET, экспортированные как COM.

Играя с кодом и комментируя части функциональных возможностей объекта .NET, мне удалось связать это с использованием объектов COM внутри объектов .NET. Обобщить:

  1. Моя программа запускает пару рабочих потоков.
  2. Каждый рабочий поток инициализирует COM-объект на основе .NET для выполнения своей работы.
  3. COM-объекты на основе .NET внутренне используют неуправляемые COM-объекты.

К моему удивлению, потребление памяти приложением начало неуклонно расти, пока не начало появляться исключение OutOfMemory.

Вот моя реализация .NET:

void DoSomeWork()
{
    IComObject O = new ComObjectClass();
    try
    {
        // do something
    }
    finally
    {
        Marshal.ReleaseComObject(O);
    }

}

Если закомментировать эту функцию, утечки памяти исчезнут. Если я вызываю в нем GC.Collect (), утечка памяти все равно происходит.

Есть идеи относительно того, что может происходить?

РЕДАКТИРОВАТЬ: Дополнительная информация на основе комментариев и ответов:

  1. Все созданные потоки выполняются в MTA.
  2. Все COM-объекты реализуют IMarshal и используют Free Threaded Marshaler.
  3. Неважно, что это за что-то - даже int i = 0; i ++; генерирует утечку.
  4. Объект, отмеченный ComObjetClass, старый и проверен. Это не значит, что он не неисправен, но это не что-то явное.
  5. Я неоднократно пытался создать COM-объект из программы на C # как в основном потоке, так и в другом созданном потоке. В обоих случаях исчезла утечка памяти. Кажется, что переход от неуправляемого кода к управляемому и обратно очень важен. Удаление любой его части приводит к исчезновению проблемы.

person Boaz    schedule 13.03.2009    source источник
comment
Что в // делать что-то? Иногда в неуправляемом коде создаются новые объекты, о которых вы не подозреваете.   -  person Grzenio    schedule 13.03.2009
comment
Есть риск, что в какой-то момент вы соедините вместе пару COM-объектов, и это вызовет утечку памяти. Код был бы полезен, чтобы понять, что происходит.   -  person sharptooth    schedule 13.03.2009
comment
Хорошо, а что, если проблема действительно в классе COM-объекта? Как будто у него неправильный механизм подсчета ссылок? Что, если вы замените его каким-нибудь другим COM-объектом?   -  person sharptooth    schedule 13.03.2009
comment
Вы можете изолировать это следующим образом: создайте образец проекта на чистом C ++, в вызове функции main () несколько раз CoCreateInstance () и IUnknown :: Release (), наблюдайте за потреблением памяти. Если утечка воспроизводима таким образом, проблема в COM-объекте.   -  person sharptooth    schedule 13.03.2009


Ответы (2)


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

Дополнительная информация содержится в этом KB.

person Brian Rasmussen    schedule 13.03.2009

Привет, предлагаю вам использовать следующий код.

     if (feature != null) 
        { 
            while (Marshal.ReleaseComObject(feature) > 0) 
            { }
            feature=null;
        }

если вы используете объект com в качестве ссылочного типа. бывший. курсор. Если вы просто выполняете Marshal.ReleaseComObject (O);

Тогда будет освобождена только одна ссылка, а остальная часть будет храниться в памяти, поэтому лучше освободить все ссылки.

person Bhaskar Singh    schedule 05.08.2014