Ви можете фактично випустити об’єкт програми Excel, але це потрібно подбати.
Порада підтримувати названу посилання для абсолютно кожного об’єкта COM, до якого ви отримуєте доступ, а потім явно відпускати через Marshal.FinalReleaseComObject()
нього, теоретично правильна, але, на жаль, дуже складно керувати на практиці. Якщо хто-небудь прослизає кудись і використовує "дві крапки", або повторює клітинки через for each
цикл або будь-яку іншу подібну команду, то ви матимете невідрегульовані об'єкти COM та ризикуєте повісити. У цьому випадку не було б можливості знайти причину в коді; вам доведеться переглянути весь код на очі і, сподіваємось, знайти причину - завдання, яке може бути майже неможливим для великого проекту.
Хороша новина полягає в тому, що вам фактично не потрібно підтримувати названу змінну посилання на кожен об’єкт COM, який ви використовуєте. Замість цього зателефонуйте GC.Collect()
та GC.WaitForPendingFinalizers()
випустіть усі (зазвичай другорядні) об'єкти, на які ви не маєте посилання, а потім явно відпустіть об'єкти, на які ви маєте вказану змінну посилання.
Ви також повинні випустити названі посилання у зворотному порядку за важливістю: спочатку об’єкти діапазону, потім робочі таблиці, робочі зошити, а потім нарешті об’єкт програми Excel.
Наприклад, якщо припустити, що у вас була названа змінна об'єкта Range, названа змінна xlRng
Workheet, названа змінна xlSheet
Workbook та змінна xlBook
програма Excel xlApp
, то ваш код очищення може виглядати приблизно так:
// Cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(xlRng);
Marshal.FinalReleaseComObject(xlSheet);
xlBook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(xlBook);
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
У більшості прикладів коду ви побачите для очищення COM об'єктів з .NET, то GC.Collect()
і GC.WaitForPendingFinalizers()
дзвінки зроблені ДВІЧІ як в:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
Однак цього не потрібно вимагати, якщо ви не використовуєте Visual Studio Tools для Office (VSTO), який використовує фіналізатори, які викликають просування цілого графа об'єктів у черзі на завершення. Такі об'єкти не будуть випущені до наступного вивезення сміття. Однак якщо ви не використовуєте VSTO, вам слід мати можливість зателефонувати GC.Collect()
і GC.WaitForPendingFinalizers()
лише один раз.
Я знаю, що явно дзвонити GC.Collect()
- це не-ні (і, звичайно, робити це вдвічі звучить дуже болісно), але, чесно кажучи, немає цього способу. Завдяки звичайним операціям ви будете генерувати приховані об'єкти, на які ви не маєте посилання, які ви, отже, не можете відпустити будь-яким іншим способом, крім дзвінків GC.Collect()
.
Це складна тема, але це справді все, що там є. Після встановлення цього шаблону для процедури очищення ви можете кодувати нормально, не потребуючи обгортки тощо :-)
У мене тут є підручник:
Автоматизація програм Office за допомогою VB.Net / COM Interop
Це написано для VB.NET, але не відкладайте на це, принципи точно такі ж, як і при використанні C #.