Утечки памяти в многопоточном приложении с использованием COM & C # - PullRequest
0 голосов
/ 13 марта 2009

Я написал многопоточное неуправляемое приложение, которое использует 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 #, как в основном потоке, так и в другом созданном потоке. В обоих случаях утечка памяти исчезла. Кажется, что необходимо перейти от неуправляемого кода к управляемому и обратно. Удаление любой его части приводит к исчезновению проблемы.

Ответы [ 2 ]

2 голосов
/ 13 марта 2009

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

В этой КБ больше информации.

0 голосов
/ 06 августа 2014

Привет предложил бы использовать следующий код.

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

, если вы используете com-объект в качестве ссылочного типа. ех. курсор. Если вы просто делаете Marshal.ReleaseComObject (О);

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

...