Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Интерфейс 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 просто не должен пытаться повторно освобождать ранее освобожденные ресурсы.

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-----"); }}





© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.