Глава.21 .Автоматическое.управление.памятью.(уборка.мусора)
ObjectDisposedException
со следующим сообщением (нет доступа к закрытому
файлу):
message: Cannot access a closed file.
using System;
using System.IO;
public static class Program {
public static void Main() {
// Создание байтов для записи во временный файл
Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 };
// Создание временного файла
FileStream fs = new FileStream("Temp.dat", FileMode.Create);
// Запись байтов во временный файл
fs.Write(bytesToWrite, 0, bytesToWrite.Length);
// Явное закрытие файла после записи
fs.Dispose();
// Попытка записи в файл после закрытия
fs.Write(bytesToWrite, 0, bytesToWrite.Length); // Исключение
ObjectDisposedException
// Удаление временного файла
File.Delete("Temp.dat");
}
}
В данном случае содержимое памяти не повреждается, так как область, выделен-
ная для объекта
FileStream
, все еще существует; просто после явного освобождения
объект не может успешно выполнять свои методы.
ВниМание
Определяя.собственный.тип,.реализующий.интерфейс.IDisposable,.обязательно.
сделайте.так,.чтобы.все.методы.и.свойства.в.случае.явной.очистки.объекта.генери-
ровали.исключение.System ObjectDisposedException .При.повторных.вызовах.методы.
Dispose.никогда.не.должны.выдавать.исключение.ObjectDisposedException.—.они.
должны.просто.возвращать.управление
ВниМание
Настоятельно.рекомендую.в.общем.случае.отказаться.от.применения.методов.
Dispose .Уборщик.мусора.из.CLR.достаточно.хорошо.написан,.и.пусть.он.делает.
свою.работу.сам .Он.определяет,.когда.объект.более.недоступен.коду.приложения,.
и.только.тогда.уничтожает.его .Вызывая.метод.Dispose,.код.приложения.фактически.
заявляет,.что.сам.«знает»,.когда.объект.становится.ненужным.приложению .Но.за-
частую.приложение.не.может.достоверно.судить.об.этом
587
Освобождение.ресурсов.при.помощи.механизма.финализации
Допустим,.у.вас.есть.код,.создающий.новый.объект .Ссылка.на.этот.объект.переда-
ется.другому.методу,.который.сохраняет.ее.в.переменной.в.некотором.внутреннем.
поле.(то.есть.в.корне),.но.вызывающий.метод.никогда.об.этом.не.узнает .Конечно.
же,.он.может.вызывать.метод.Dispose,.но.если.какой-то.код.попытается.обратиться.
к.этому.объекту,.будет.выдано.исключение.ObjectDisposedException .Я.рекомендую.
вызывать.методы.Dispose.только.там,.где.можно.точно.сказать,.что.потребуется.
очистка.ресурса.(как.в.случае.с.попыткой.удаления.открытого.файла)
Кроме.того,.несколько.потоков.могут.одновременно.вызвать.Dispose.для.одного.
объекта .В.рекомендациях.проектирования.указано,.что.метод.Dispose.не.обязан.
быть.безопасным.по.отношению.к.потокам .Дело.в.том,.что.код.должен.вызывать.
Dispose.только.в.том.случае,.если.он.твердо.уверен,.что.объект.не.используется.
другими.потоками
Приведенные примеры кода демонстрируют методику явного вызова метода
Dispose
. Если вы решили воспользоваться явным вызовом, настоятельно рекомен-
дую поместить его в блок обработки исключений
finally
, так как это гарантирует
исполнение кода очистки. Соответственно код из предыдущего примера лучше
переписать так:
using System;
using System.IO;
public static class Program {
public static void Main() {
// Создание байтов для записи во временный файл
Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 };
// Создание временного файла
FileStream fs = new FileStream("Temp.dat", FileMode.Create);
try {
// Запись байтов во временный файл
fs.Write(bytesToWrite, 0, bytesToWrite.Length);
}
finally {
// Явное закрытие файла после записи
if (fs != null)
fs.Dispose();
}
// Удаление временного файла
File.Delete("Temp.dat");
}
}
Здесь хорошо было бы добавить код для обработки исключений — не поленитесь
это сделать. К счастью, в C# есть инструкция
using
, предлагающая упрощенный
синтаксис генерации кода, идентичного показанному. Вот как можно переписать
предыдущий код с помощью этой инструкции:
588
Do'stlaringiz bilan baham: |