Пока кажется, что все ответы включают некоторые из них:
- убить процесс
- Использовать GC.Collect ()
- Отслеживайте каждый COM-объект и освобождайте его должным образом.
Что заставляет меня оценить, насколько сложна эта проблема:)
Я работаю над библиотекой, чтобы упростить доступ к Excel, и я стараюсь сделать так, чтобы люди, использующие ее, не оставили беспорядок (скрестив пальцы).
Вместо того, чтобы писать непосредственно на интерфейсах, которые предоставляет Interop, я делаю методы расширения, чтобы облегчить жизнь. Как ApplicationHelpers.CreateExcel () или workbook.CreateWorksheet ("mySheetNameThatWillBeValidated"). Естественно, все, что создано, может привести к проблеме позже при очистке, поэтому я на самом деле предпочитаю убить процесс как последнее средство. Тем не менее, очистка должным образом (третий вариант), вероятно, является наименее разрушительной и наиболее контролируемой.
Итак, в этом контексте мне было интересно, не лучше ли было бы сделать что-то вроде этого:
public abstract class ReleaseContainer<T>
{
private readonly Action<T> actionOnT;
protected ReleaseContainer(T releasible, Action<T> actionOnT)
{
this.actionOnT = actionOnT;
this.Releasible = releasible;
}
~ReleaseContainer()
{
Release();
}
public T Releasible { get; private set; }
private void Release()
{
actionOnT(Releasible);
Releasible = default(T);
}
}
Я использовал «Releasible», чтобы избежать путаницы с Disposable. Расширить это до IDisposable должно быть легко.
Реализация, подобная этой:
public class ApplicationContainer : ReleaseContainer<Application>
{
public ApplicationContainer()
: base(new Application(), ActionOnExcel)
{
}
private static void ActionOnExcel(Application application)
{
application.Show(); // extension method. want to make sure the app is visible.
application.Quit();
Marshal.FinalReleaseComObject(application);
}
}
И можно сделать что-то подобное для всех видов COM-объектов.
В заводском методе:
public static Application CreateExcelApplication(bool hidden = false)
{
var excel = new ApplicationContainer().Releasible;
excel.Visible = !hidden;
return excel;
}
Я ожидаю, что GC уничтожит каждый контейнер должным образом, и поэтому автоматически сделает вызов Quit
и Marshal.FinalReleaseComObject
.
Комментарии? Или это ответ на вопрос третьего рода?