Здравствуйте, Аноним, Вы писали:
А>Как быть, если в Dispose вызывается Dispose другого класса, который кидает OutOfMemoryException.
В общем случае — никак, в частном — только если задача решается с помощью CER-блока.
АутОфМемори — это грубо говоря полный финиш и лучше рухнуть с перезапуском.
Здравствуйте, hardcase, Вы писали:
H>>АутОфМемори — это грубо говоря полный финиш и лучше рухнуть с перезапуском.
H>И если не ошибаюсь оно вообще не перехватывается так как имеет асинхронную природу.
Перехватывается.
Да и не всегда это полный финиш. Например, пользователь мог выбрать в меню какую-то ресурсоемкую операцию (построенние какого-нибудь аналитического отчета), внутри которой мы пытаемся выделить массив в 500 Мб. Получаем OOM и там же перехватываем. Говорим: извините, для этой операции не хватает ресурсов. Но работу с приложением можно продолжать, потому что никакие данные не повреждены, не потеряны, программа в согласованном состоянии.
Если "другой класс" нельзя сделать по-нормальному, то так как выше сделать можно (дае нужно), но только необходимо в catch написать коментарий о том, какой автор класса Bar нехороший человек и пожелать ему долгих и счастливых лет жизни.
Help will always be given at Hogwarts to those who ask for it.
To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.
ИМХО выделенная фраза относится к "should be callable multiple times", т.е. имеется ввиду, что метод Dispose должен учитывать возможность повторных вызовов и нормально отрабатывать (т.е. ничего не делать), а не выкидывать исключение. В примере по ссылке такое поведение реализуется при помощи приватного поля _disposed.
To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.
A>ИМХО выделенная фраза относится к "should be callable multiple times", т.е. имеется ввиду, что метод Dispose должен учитывать возможность повторных вызовов и нормально отрабатывать (т.е. ничего не делать), а не выкидывать исключение. В примере по ссылке такое поведение реализуется при помощи приватного поля _disposed.
Нет, это не так: и для объяснения этого вовсе не обязательно даже МСДН читать. Представим, что Dispose() бросает исключение (а уже нашлись добрые люди, которые довели до этого некоторые классы во фреймворке) на законных основаниях. В таком случае, как должен вести себя код, который имеет несколько IDisposable и желает их все освободить? Этот код должен каждый вызов Dispose() заключать в try-catch или в try-finally — иначе этому коду будет невозможно освободить другие ресурсы. Это было бы очень жестоко по отношению к программистам.
Ну, а подходя с формальной стороны, принимая слова о том, к чему относится "выделенная фраза", за правду, стоит удивиться: как это так — при первом вызове метод может бросить исключение, а при повторных — уже нет?
Help will always be given at Hogwarts to those who ask for it.
To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.
A>ИМХО выделенная фраза относится к "should be callable multiple times", т.е. имеется ввиду, что метод Dispose должен учитывать возможность повторных вызовов и нормально отрабатывать (т.е. ничего не делать), а не выкидывать исключение. В примере по ссылке такое поведение реализуется при помощи приватного поля _disposed.
To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.
A>>ИМХО выделенная фраза относится к "should be callable multiple times", т.е. имеется ввиду, что метод Dispose должен учитывать возможность повторных вызовов и нормально отрабатывать (т.е. ничего не делать), а не выкидывать исключение. В примере по ссылке такое поведение реализуется при помощи приватного поля _disposed.
_FR>Нет, это не так: и для объяснения этого вовсе не обязательно даже МСДН читать. Представим, что Dispose() бросает исключение (а уже нашлись добрые люди, которые довели до этого некоторые классы во фреймворке) на законных основаниях. В таком случае, как должен вести себя код, который имеет несколько IDisposable и желает их все освободить? Этот код должен каждый вызов Dispose() заключать в try-catch или в try-finally — иначе этому коду будет невозможно освободить другие ресурсы. Это было бы очень жестоко по отношению к программистам.
_FR>Ну, а подходя с формальной стороны, принимая слова о том, к чему относится "выделенная фраза", за правду, стоит удивиться: как это так — при первом вызове метод может бросить исключение, а при повторных — уже нет?
И при втором можно, только не нужно делать так:
if (disposed)
throw new InvalidOperationException("Already disposed.");
Об этом "should be callable multiple times" и говорит. И Dispose обычно через using вызывается, поэтому задача явного вызвать нескольких Dispose не так часто стоит.
H>В общем случае — никак, в частном — только если задача решается с помощью CER-блока. H>АутОфМемори — это грубо говоря полный финиш и лучше рухнуть с перезапуском.
сходу вспоминаю моменты когда работа с System.Drawing при ресайзе картинок например может кинуть это исключение, второе это загрузка большого xml, в обоих случаях можно перехватить как справедливо указал nikov и продолжить работу.
Здравствуйте, anton_t, Вы писали:
_FR>>Ну, а подходя с формальной стороны, принимая слова о том, к чему относится "выделенная фраза", за правду, стоит удивиться: как это так — при первом вызове метод может бросить исключение, а при повторных — уже нет?
_>И при втором можно, только не нужно делать так:
_>if (disposed)
_> throw new InvalidOperationException("Already disposed.");
_>Об этом "should be callable multiple times" и говорит.
Не вижу из ваших слов объяснения "почему" Ведь чётко же сказано:
…a Dispose method should be callable multiple times without throwing an exception.
А если Dispose() реализован ват так, например:
void Dispose() {
throw new Exception();
}
То при повторном и последующих вызовах написанное будет нарушено.
_>И Dispose обычно через using вызывается, поэтому задача явного вызвать нескольких Dispose не так часто стоит.
Что значит "обычно"? using применим _только_ для локальных переменных. Когда у вас в классе етсь поле типа IDisposable, using вам не поможет. А о том, что "стоит чаще" я бы затруднился сказать — не имею статистики.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, anton_t, Вы писали:
_FR>>>Ну, а подходя с формальной стороны, принимая слова о том, к чему относится "выделенная фраза", за правду, стоит удивиться: как это так — при первом вызове метод может бросить исключение, а при повторных — уже нет?
_>>И при втором можно, только не нужно делать так: _FR>
_>>if (disposed)
_>> throw new InvalidOperationException("Already disposed.");
_FR>
_>>Об этом "should be callable multiple times" и говорит.
_FR>Не вижу из ваших слов объяснения "почему" Ведь чётко же сказано: _FR>
_FR>…a Dispose method should be callable multiple times without throwing an exception.
А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код:
File.Delete(tmpFilePath);
По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?
Здравствуйте, anton_t, Вы писали:
_>Здравствуйте, _FRED_, Вы писали:
_>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код: _>
_>File.Delete(tmpFilePath);
_>
_>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?
Если этот код в Dispose — да. Опционально — залогировать.
Здравствуйте, Aen Sidhe, Вы писали:
AS>Здравствуйте, anton_t, Вы писали:
_>>Здравствуйте, _FRED_, Вы писали:
_>>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код: _>>
_>>File.Delete(tmpFilePath);
_>>
_>>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?
AS>Если этот код в Dispose — да. Опционально — залогировать.
А если логгер в этом Dispose не доступен? Просто проглотить исключение? И потом гадать на кофеной гуще, чего это у клиента темповая дира всё дисковое пространство занимает?
Здравствуйте, anton_t, Вы писали:
AS>>Если этот код в Dispose — да. Опционально — залогировать.
_>А если логгер в этом Dispose не доступен? Просто проглотить исключение? И потом гадать на кофеной гуще, чего это у клиента темповая дира всё дисковое пространство занимает?
Если у вас такой замечательный логгер, то да, разумеется, надо наплевать на стандарт и плеваться исключениями налево и направо, раз он недоступен. Кто же запретит то.
Здравствуйте, anton_t, Вы писали:
AS>>Если этот код в Dispose — да. Опционально — залогировать.
_>А если логгер в этом Dispose не доступен? Просто проглотить исключение? И потом гадать на кофеной гуще, чего это у клиента темповая дира всё дисковое пространство занимает?
Проблема в том, что одно из исключений в любом случае рискует быть проглоченным. И лучше сделать это явно в методе Dispose, и приложить все усилия, чтобы успешно залогировать там же.
using System;
using System.IO;
class A : IDisposable
{
public void Dispose()
{
throw new IOException("Cannot clean up resources in file systsem for some reason");
}
static void Main()
{
try
{
using(new A())
{
// Это исключение теряетсяthrow new InvalidOperationException("Something really bad happened");
}
}
catch (Exception e)
{
Console.WriteLine(e); // IOException
}
}
}
Здравствуйте, anton_t, Вы писали:
_FR>>Не вижу из ваших слов объяснения "почему" Ведь чётко же сказано: _FR>>
_FR>>…a Dispose method should be callable multiple times without throwing an exception.
_>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код:
_>File.Delete(tmpFilePath);
_>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?
Самый очевидный способ — не засовывать такой код в Dispose()
Вызывать DeleteFile()
Обернуть соответствующим try-catch.
Только так можно избавить от гемороя тех, кто будет такой объект использовать. Иначе же наоборот, теряется весь смысл using-а — вызывающий код обязан оборачивать вызовы Dispose() в try-catch, впрочем, я об этом выше уже сказал.
Help will always be given at Hogwarts to those who ask for it.