Российский Государственный Технологический Университет им. К.Э. Циолковского
Опубликован: 02.03.2007 | Доступ: свободный | Студентов: 5636 / 790 | Оценка: 3.96 / 3.45 | Длительность: 27:04:00
ISBN: 978-5-9556-0086-4
Лекция 8:

Интерфейсы

< Лекция 7 || Лекция 8: 123 || Лекция 9 >

Интерфейс IDisposable. Освобождение ресурсов

Совмещение освобождения ресурсов с удалением объекта-владельца данного ресурса называется недетерминированным освобождением. Зависящее от деятельности сборщика мусора недетерминированное освобождение ресурсов не всегда является оптимальным решением:

  • время начала очередного цикла работы GC обычно неизвестно;
  • будет ли удален соответствующий объект в случае незамедлительной активизации GC;
  • что делать, если ресурс необходимо освободить незамедлительно, а объект должен быть сохранен.

Для детерминированного освобождения неуправляемых ресурсов может быть использован какой-либо специальный метод. Этот метод желательно сделать универсальным, по крайней мере, в смысле его объявления и вызова.

В этом случае для любого вновь объявляемого класса можно предположить существование метода с предопределенным именем и сигнатурой (спецификацией типа возвращаемого значения и списком параметров), который можно было бы стандартным образом вызывать непосредственно от имени объекта-владельца ресурса вне зависимости от активности системы очистки памяти.

В .NET с этой целью используется интерфейс IDisposable с методом Dispose.

public interface IDisposable
{
 void Dispose();
}

Таким образом, для реализации механизма освобождения ресурсов достаточно наследовать интерфейс IDisposable и обеспечить реализацию метода Dispose. После этого деятельность по освобождению ресурсов сводится к теперь стандартному выражению вызова метода Dispose.

Следующие правила определяют в общих чертах рекомендации по использованию метода Dispose.

В методе Dispose освобождаются любые ресурсы, которыми владеет объект данного типа и которые можно освободить.

Если для освобождения ресурсов, которыми владеет объект, не был вызван метод Dispose, неуправляемые ресурсы должны освобождаться в методе Finalize.

Метод Dispose может дублировать действия по освобождению ресурсов, предпринимаемые в деструкторе ( Finalize ) при уничтожении объекта. Для этого можно предусмотреть систему булевых переменных, связанных с состоянием ресурса, или вызов для данного объекта метода GC.SuppressFinalize, который для этого объекта запретит выполнение кода деструктора, соответствующего в C# коду метода Finalize. Означает ли это, что GC уничтожит объект, не передавая при этом управление деструктору?

Метод Dispose должен освобождать все ресурсы, удерживаемые данным объектом и любым объектом, которым владеет данный объект.

Следует обеспечить возможность многократного вызова метода. При этом желательно обойтись без генерации исключений. Dispose просто не должен пытаться повторно освобождать ранее освобожденные ресурсы.

using System;

namespace TestD00
{
public class MemElem : IDisposable
{
bool dFlag;
int i;
public MemElem(int iKey)
{
dFlag = true;
i = iKey;
}

~MemElem() // Деструктор (он же Finalizer)
{
Console.WriteLine("{0} disposed : {1}!", i, (dFlag == true) ? "yes" : "no");
// Если ресурсы не освобождены – вызывается Dispose. 
if (!dFlag) Dispose();
}
// Детерминированное управление ресурсом:
// имитация активности.
public void Dispose()
{
if (dFlag==true)
{
 Console.WriteLine("Dispose is here!");
 dFlag = false;
} 
else
{
 Console.WriteLine("Dispose was here!");
}  
}               
}
    
class Program
{
static void Main(string[] args)
{
IDisposable d;
MemElem mmm = null;
int i;
for (i = 0; i < 10; i++)
{
MemElem m = new MemElem(i);
if (i == 5) 
{
 d = m as IDisposable;
 if (d!=null) d.Dispose();
 mmm = m;
 GC.SuppressFinalize(mmm); // И закрыли для кода деструктора.
}
}

Console.WriteLine("-----0-----");
GC.Collect();
Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));
// Заменить false на true. Осознать разницу.
Console.WriteLine("-----1-----");
// А теперь вновь разрешили его удалить...
// Пока существует хотя бы одна ссылка – GC все равно не будет
// уничтожать этот объект. 
if (mmm != null) GC.ReRegisterForFinalize(mmm);
mmm = null; // Вот потеряли ссылку на объект.
// Теперь GC может уничтожить объект. Если разрешена финализация - 
// будет выполнен код деструктора. Возможно, что отработает метод
// Dispose. Если финализация запрещена -
// код деструктора останется невыполненным.
Console.WriteLine("-----2-----");
GC.Collect();
// Заменить false на true. Осознать разницу.
Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));
Console.WriteLine("-----3-----");
}
}
}
Листинг 8.4.
< Лекция 7 || Лекция 8: 123 || Лекция 9 >
kewezok kewezok
kewezok kewezok
Елена Шляхт
Елена Шляхт
Объясните плиз в чем отличие а++ от ++а
Почему результат разный?
int a=0, b=0;
Console.WriteLine(a++); //0
Console.WriteLine(++b); //1
a++;
++b;
Console.WriteLine(a); //2
Console.WriteLine(b); //2