Как я могу закрыть Excel, когда я закончу с этим? - PullRequest
0 голосов
/ 31 декабря 2018

Это в надстройке COM API Word.И да, обычно Совет Ханса Пассанта разрешить .NET очистить все работает .

Но это не работает в следующем случае - и я протестировал работу нормально (без отладчика) и сузилсяэто до этого конкретного кода:

private Chart chart;
private bool displayAlerts;
private Application xlApp;


Chart chart = myShape.Chart;

ChartData chartData = chart.ChartData;
chartData.Activate();

WorkbookData = (Workbook)chartData.Workbook;
xlApp = WorkbookData.Application;
displayAlerts = xlApp.DisplayAlerts;
xlApp.Visible = false;
xlApp.DisplayAlerts = false;
WorksheetData = (Worksheet)WorkbookData.Worksheets[1];
WorksheetDataName = WorksheetData.Name;
WorksheetData.UsedRange.Clear();

// ... do a bunch of stuff including writing to the worksheet

xlApp.DisplayAlerts = displayAlerts;
WorkbookData.Close(true);

Я думаю, что проблема, скорее всего, Word дает мне эту книгу, и поэтому кто знает, что он делает для создания экземпляра Excel.Но даже после выхода из Word экземпляр Excel все еще работает.

Опять же, в Word (не в Excel) доступ к объекту диаграммы для обновления данных в диаграмме.

1 Ответ

0 голосов
/ 06 января 2019

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

Этот конкретный случай может быть особенным (по сравнению с другим кодом, который вы использовали ранее) из-за использования xlApp.По умолчанию объект Excel Application не нужен или не используется при манипулировании диаграммами с помощью объектной модели, представленной в Office 2007 (я думаю, что это было).Он используется в коде в вопросе, чтобы скрыть окно Excel, которое видно по умолчанию (и по дизайну).Но объектная модель не предназначена для очистки этого - она ​​предполагает, что ее нет ...

В моих тестах объект освобождается правильно, когда (ссылаясь на код в вопросе):

Все объекты Excel установлены на null в обратном порядке, в котором они создаются , обязательно выйдет из приложения Excel, прежде чем пытаться установить этот объект на null:

WorksheetData = null; 
WorkbookData = null; 
xlApp.Quit(); 
xlApp = null; 

Затем, C # имеет тенденцию создавать объекты за сценой, когда используется точечная запись COM - они не всегда очищаются (освобождаются) должным образом.Поэтому хорошей практикой является создание объекта для каждого уровня используемой иерархии.(Примечание: VBA не имеет этой проблемы, поэтому любой код, взятый из примера VBA или устройства записи макросов, должен быть переработан в этом отношении.) Из кода в вопросе это влияет на WorksheetData.UsedRange.Clear();

Excel.Range usedRng = WorksheetData.UsedRange; 
usedRng.Clear(); 
usedRng = null; 

И стандартная очистка, чтобы убедиться, что все выпущено в предсказуемый момент:

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

Когда такие вещи возникают, я всегда обращаюсь к ".NET Development for Office"Эндрю УайтчепелЭто действительно «голые кости», и некоторые из них больше не актуальны, учитывая изменения в C #, которые были сделаны с годами (чтобы сделать его «более легким в использовании», как VB.NET «проще»).Но то, как COM взаимодействует с .NET, глубоко не изменилось ...

...