Выпуск COM-объектов .NET force

У меня есть приложение ASP.NET 2.0 под IIS, которое имеет функцию экспорта некоторых данных в программное обеспечение под названием HFM (Oracle Hyperion Financial Management). Для выполнения этого экспорта приложение .net использует API, основанный на COM-объектах, предоставляемых клиентом HFM (клиент устанавливается на том же компьютере, что и сервер, и т. Д.)

Моя проблема в том, что API предоставляет метод для подключения к серверу HFM, но не для отключения.
В документации сказано, что для отключения приложение должно вызывать метод Marshal.ReleaseComObject () на каждом COM-объект создан. Но выполняется много сложных действий, и я не могу освободить весь созданный объект.
Итак, мое приложение не отключается.

Я заметил, что когда я заменяю файлы dll приложения ASP.NET (которые, кажется, повторно инициализируют объекты, созданные .NET), приложение автоматически отключается.

Несколько раз пробовала позвонить:

GC.Collect();
GC.WaitForPendingFinalizers();

Но проблема остается. Я ищу способ быть уверенным, что ЛЮБОЙ объект создан, даже COM-объекты выпущены. Я пробовал использовать Marshal.FinalReleaseComObject (), но это не лучше.

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

Есть ли способ узнать, какой объект или, по крайней мере, тип объекта, который не был выпущен?

Спасибо за вашу помощь.


person Julien N    schedule 06.01.2009    source источник


Ответы (3)


Но выполняется много сложных действий, и я не могу освободить весь созданный объект.

Вот твоя проблема.

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

person yfeldblum    schedule 06.01.2009
comment
Вы были правы, после тщательного анализа и упрощения процесса мы заметили, что какой-то объект не был выпущен должным образом. Это было причиной проблемы. - person Julien N; 14.07.2010

Можно ли разместить вокруг каждого из этих экземпляров COM универсальный тип оболочки, реализующий IDisposable?

Затем вы можете вызвать Marshal.FinalReleaseComObject (или выполнить цикл Marshal.ReleaseComObject, проверяя счетчик ссылок) в методе Dispose и создать только экземпляр COM-объекта. с помощью оператора using, который ссылается на ваш тип оболочки.

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

person HTTP 410    schedule 06.01.2009

Абсолютно важно установить для переменной значение Null / Nothing после вызова Marshal.ReleaseComObject или Marshal.FinalReleaseComObject.

Dim cn As ADODB.Connection
cn = New ADODB.Connection
cn.Open(_cnnstr)
cn.Execute(sbDML.ToString)
cn.Close()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cn)
cn = Nothing '!!!IMPORTANT!!! - Do not remove, MUST be explicitly called!

Кроме того, я заметил, что создание другого метода помогает избежать проблем с работой с локальными COM-объектами (переменные, помещенные в стек). Например, если у вас есть один метод, который делает все, оберните его в другой метод, добавьте вызов к сборке мусора, а затем вызовите оболочку.

Public Sub MainMethod
    '...
    Marshal.FinalReleaseComObject(foo)
    foo = Nothing '!!!IMPORTANT!!! - Do not remove, MUST be explicitly called!
End Sub

Public Sub WrapperMethod
    Call MainMethod
    GC.Collect()
End Sub

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

Я следую этому образцу уже пару лет, и с тех пор у меня не было никаких проблем.

person AMissico    schedule 01.12.2009