2010-12-21 3 views
7

У меня есть приложение, которое использует COM-взаимодействие для создания электронной таблицы, которая открывается в Excel на машине клиента. Однако представляется, что процесс EXCEL.exe не всегда заканчивается, когда пользователь закрывает Excel, если я смотрю на Диспетчер задач.Проблема с зависанием объектов COM COM

Если бы я сохранил книгу и программно закрыл Excel, я бы просто использовал Marshal.ReleaseComObject() для очистки, но поскольку я в зависимости от закрытия программы вручную, я не уверен, что делать. Какие-либо предложения?

ответ

9

Excel не может быть завершен до тех пор, пока не будут освобождены все его объекты вне процесса. Таким образом, он просто скрывает свой пользовательский интерфейс и продолжает работать. До тех пор, пока ваша программа не завершит работу или не удалит все ссылки на объекты Excel и поток финализатора. Выход из вашей программы станет очевидным решением. Или вы можете заставить финализатор нить для работы с:

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

ReleaseComObject() редко работает, потому что это так легко забыть посредническую ссылку COM объекта. Подобно WorkBooks [index], это перечислитель, которого вы не видите. Предоставление ГК такого решения для себя было бы более разумным выбором, если вы продолжаете работать и выполняете работу, тогда это произойдет.

+0

'GC.Collect()' и 'GC.WaitForPendingFinalizers()', казалось, сделали трюк. –

3

Возможно, файл Excel.exe по-прежнему открыт, потому что пользователь открыл другой документ в том же экземпляре приложения Excell. В этом случае вы, вероятно, не должны убивать процесс Excel.exe.

Если вы закроете все открытые документы и освободите все созданные вами объекты, то почему вам важно убедиться, что Excel.exe завершен? Может быть, процесс обслуживает другое приложение или пользователя?

2

Может быть много причин (включая Ran's), но я вижу много с MapPoint (другое приложение Microsoft со COM-интерфейсом), так что вы должны убедиться, что ВСЕ ссылки на объекты очищены, чтобы сборщик мусора мог их очистить вверх. Достаточно одного низкого объекта, чтобы остановить приложение от закрытия и выхода из списка процессов.

+1

Каков наилучший способ удаления этих ссылок на объекты? Должен ли я использовать 'ReleaseComObject()'? –

+1

Похоже, Ганс уже ответил. Установите ссылки на нуль. Если этого недостаточно, запустите GC.Collect при завершении. .NET обычно хорошо обрабатывает COM (например, старый VB6), и вам не нужно слишком беспокоиться о деталях под капотом. – winwaed

2

Если открыть приложение Excel и книгу с:

Excel.Application app = new Excel.Application(); 
Excel.Workbook wb = app.Workbooks.Open(...); 

Затем я использую wb.Close(), app.Quit() методы в заявлении, наконец (или другого соответствующего события закрытия). Это очищает процесс Exel.exe. Не нужно вызывать методы Marshall.ReleaseComObject или GC.

Смежные вопросы