Все эти вопросы:
- Excel 2007 зависает при закрытии через .NET
- Как правильно очистить объекты взаимодействия Microsoft в С#
- Как правильно очистить объекты взаимодействия на С#
бороться с проблемой, что С# не освобождает объекты COM Excel должным образом после их использования. В этом вопросе есть главным образом два направления:
- Убейте процесс Excel, когда Excel больше не используется.
- Позаботьтесь о том, чтобы явно назначить каждый COM-объект, используемый для переменной, и гарантировать, что в конечном итоге Marshal.ReleaseComObject будет выполняться на каждом из них.
Итак, я думал о решении 2, создав еще одну прокси-объектную модель, которая имитирует объектную модель Excel (для меня было бы достаточно реализовать объекты, которые мне действительно нужны). Принцип будет выглядеть следующим образом:
- Каждый класс Excel Interop имеет свой прокси-сервер, который обертывает объект этого класса.
- Прокси-сервер выпускает COM-объект в своем финализаторе.
- Прокси имитирует интерфейс класса Interop.
- Любые методы, которые первоначально возвратили COM-объект, изменяются для возврата прокси-сервера. Другие методы просто делегируют реализацию внутреннему COM-объекту.
Пример:
public class Application
{
private Microsoft.Office.Interop.Excel.Application innerApplication
= new Microsoft.Office.Interop.Excel.Application innerApplication();
~Application()
{
Marshal.ReleaseCOMObject(innerApplication);
innerApplication = null;
}
public Workbooks Workbooks
{
get { return new Workbooks(innerApplication.Workbooks); }
}
}
public class Workbooks
{
private Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks;
Workbooks(Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks)
{
this.innerWorkbooks = innerWorkbooks;
}
~Workbooks()
{
Marshal.ReleaseCOMObject(innerWorkbooks);
innerWorkbooks = null;
}
}
Мои вопросы для вас в частности:
- Кто считает эту плохую идею и почему?
- Кто считает эту идею ужасом? Если да, то почему никто не реализовал и не опубликовал такую модель? Это только благодаря усилиям, или мне не хватает проблемы с убийством с этой идеей?
- Невозможно ли/неправильно/подвержено ошибкам делать ReleaseCOMObject в финализаторе? (Я только видел предложения поместить его в Dispose(), а не в финализатор - почему?)
- Если подход имеет смысл, любые предложения по его улучшению?