У меня есть приложение WinForms, которое использует COM Interop для подключения к приложениям Microsoft Office. Я прочитал много материала о том, как правильно распоряжаться COM объектов и здесь типичный код из моего приложения, используя методы из собственной статьи от Microsoft (here):Освобождение COM-объектов в .NET изнутри перечислений и других ссылочных сценариев
Excel.Application excel = new Excel.Application();
Excel.Workbook book = excel.Workbooks.Add();
Excel.Range range = null;
foreach (Excel.Worksheet sheet in book.Sheets)
{
range = sheet.Range["A2:Z2"];
// Process [range] here.
range.MergeCells();
System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
range = null;
}
// Release explicitly declared objects in hierarchical order.
System.Runtime.InteropServices.Marshal.ReleaseComObject(book);
System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);
book = null;
excel = null;
// As taken from:
// http://msdn.microsoft.com/en-us/library/aa679807(v=office.11).aspx.
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
Вся обработка исключений была лишена, чтобы сделать код clearer для этого вопроса.
Что происходит с объектом [sheet]
в цикле [foreach]
? Предположительно, он не будет очищен, и мы не будем вмешиваться в него, пока он перечисляется. Одним из вариантов было бы использовать цикл индексирования, но это делает уродливый код, а некоторые конструкторы в библиотеках объектов Office даже не поддерживают индексацию.
Кроме того, цикл [foreach]
ссылается на коллекцию [book.Sheets]
. Оказывает ли это сиротство RCW?
Так два вопроса:
- Каков наилучший подход к очистке при перечислении необходимо?
- Что происходит с промежуточными объектами, такими как
[Sheets]
в[book.Sheets]
, так как они явно не объявлены или не очищены?
UPDATE:
Я был удивлен предложением Ханс Passant и счел необходимым обеспечить некоторый контекст.
Это клиент/серверное приложение, в котором клиент подключается к различным приложениям Office, включая Access, Excel, Outlook, PowerPoint и Word. Он имеет более 1500 классов (и растет), которые тестируют определенные задачи, выполняемые конечными пользователями, а также имитируют их в режиме обучения. Он используется для обучения и тестирования студентов в области владения офисом в академической среде. С несколькими разработчиками и множеством классов было сложно обеспечить соблюдение COM-совместимых методов кодирования. В конечном итоге я прибегал к созданию автоматических тестов с использованием комбинации анализа и анализа исходного кода, чтобы обеспечить целостность этих классов на этапе предварительного просмотра кода.
Пожелает предложению Ганса попробовать вернуться.
Удалить все вызовы ReleaseComObject(). Создайте версию версии своей программы и запустите ее без отладчика. И используйте диспетчер задач, чтобы убедиться, что он работает отлично, без помощи. –
Там никогда не бывает недостатка в мнениях вудов и необоснованных претензий, когда дело доходит до управления памятью COM. Недостаточно котировок вокруг «официальных», читайте, что команда VS [думает о практике] (http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered- dangerous.aspx). –
@ ХансПасант: Спасибо. Я этого не думал и никогда не слышал. Мое приложение подключается к 7 различным приложениям Office (на стороне клиента, а не к серверному приложению) и по существу построено вокруг них (но не как надстройка, хотя). Поэтому, учитывая тяжелое взаимодействие, я, естественно, пользовался большой осторожностью. К счастью, я использовал принудительные методы для Interop, поэтому попытка, которую вы предлагаете, будет очень простой, несмотря на 1500+ классов, которые взаимодействуют с приложениями Office. Вернется обратно. –