class _1CObject : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
}
if (Obj != null && Obj.GetType().IsCOMObject)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(Obj);
}
Obj = null;
}
~_1CObject()
{
Dispose(false);
}
static public object _v81Connector;
/// <summary>
/// COM объект
/// </summary>
public object Obj;
Сборка мусора, COM объекты, OutOfMemory
Код:
Методы COM объекта возвращают либо ссылку на другой COM объект, либо ValueType (строки или числа). Не зависимо от типа, результат я сохраняю в поле своего класса (Obj). При Dispose я проверяю естественно COM объект это или нет (делать или нет Release). COM объекты которые у нас создаются в результате вызовов, могут быть достаточно большими, как-раз в эти моменты я получаю OutOfMemory.
Вопросы:
1)Должен ли я как-то очищать поле Obj если там хранится ValueType(Int32, Boolean...) и как если должен? Я ведь помечаю, чтобы GC не трогал мой объект GC.SuppressFinalize(this); (возможна утечка через эти типы).
2)Может ли выскакивать это исключение, если утечки памяти нету? Не может например найти память под большой COM объект. GC в этом случае делает дефрагментацию и сборку, если ему не хватает места под COM?
Примечание: если не делать частых вызовов, то утечки не заметно (несколько дней работает нормально). Если вызовы очень частые и COM объекты большие создаем, то спасает вставка
Код:
if (Obj != null && Obj.GetType().IsCOMObject)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(Obj);
}
Obj = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(Obj);
}
Obj = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
http://msdn.microsoft.com/ru-ru/library/9w766t6y.aspx
Это исключение может быть сгенерировано с дополнительным сообщением: Недостаточно свободной памяти для завершения этой операции, которое появляется при вызове метода для объекта COM, возвращающем определяемый пользователем тип, содержащий безопасный массив (массив не фиксированного размера). Это происходит, потому что .NET Framework. не может маршалировать поля структуры с безопасным типом массива.
Как решение, сейчас использую чистку GC при вызове этого исключения
Нечего на GC пенять. COM объекты создаются в вообще в другой куче - неуправляемой.
Это ведь и есть очистка COM объекта. Dispose вызываю. На случай если где-то забыл, я ведь Finalizator определил. Проблем нету, если GC.Collection делать и если запускаю на машинах больше 1 гб. Вываливается ошибка только когда COM объект пытается вернуть большие(!) "массивы".