IDisposable.Dispose() и Exception
От: Аноним  
Дата: 23.06.10 10:56
Оценка:
Вопрос дизайна, стоит ли перехватывать исключения в Dispose?
Re: IDisposable.Dispose() и Exception
От: Aen Sidhe Россия Просто блог
Дата: 23.06.10 10:59
Оценка: 1 (1) +1
Здравствуйте, Аноним, Вы писали:

А>Вопрос дизайна, стоит ли перехватывать исключения в Dispose?


http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.

С уважением, Анатолий Попов.
ICQ: 995-908
Re[2]: IDisposable.Dispose() и Exception
От: Аноним  
Дата: 23.06.10 14:08
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

AS>

To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.


Как быть, если в Dispose вызывается Dispose другого класса, который кидает OutOfMemoryException.
public class Foo: IDisposable
{
    private Bar _bar;
    void Dispose()
    {
       if (_bar != null)
       {
          try
          {
             _bar.Dispose();
          }
          catch (OutOfMemoryException)
          {
          }
          _bar = null;
       }
    }
}
Re[3]: IDisposable.Dispose() и Exception
От: xobotik Россия  
Дата: 23.06.10 19:40
Оценка:
Здравствуйте, Аноним, Вы писали:

Сделать так, чтобы не кидал
С уважением!
Re[3]: IDisposable.Dispose() и Exception
От: hardcase Пират http://nemerle.org
Дата: 23.06.10 19:40
Оценка: +2
Здравствуйте, Аноним, Вы писали:

А>Как быть, если в Dispose вызывается Dispose другого класса, который кидает OutOfMemoryException.


В общем случае — никак, в частном — только если задача решается с помощью CER-блока.
АутОфМемори — это грубо говоря полный финиш и лучше рухнуть с перезапуском.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: IDisposable.Dispose() и Exception
От: hardcase Пират http://nemerle.org
Дата: 23.06.10 19:41
Оценка:
Здравствуйте, hardcase, Вы писали:

H>АутОфМемори — это грубо говоря полный финиш и лучше рухнуть с перезапуском.


И если не ошибаюсь оно вообще не перехватывается так как имеет асинхронную природу.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[5]: IDisposable.Dispose() и Exception
От: nikov США http://www.linkedin.com/in/nikov
Дата: 24.06.10 06:03
Оценка: 2 (1) +2
Здравствуйте, hardcase, Вы писали:

H>>АутОфМемори — это грубо говоря полный финиш и лучше рухнуть с перезапуском.


H>И если не ошибаюсь оно вообще не перехватывается так как имеет асинхронную природу.


Перехватывается.
Да и не всегда это полный финиш. Например, пользователь мог выбрать в меню какую-то ресурсоемкую операцию (построенние какого-нибудь аналитического отчета), внутри которой мы пытаемся выделить массив в 500 Мб. Получаем OOM и там же перехватываем. Говорим: извините, для этой операции не хватает ресурсов. Но работу с приложением можно продолжать, потому что никакие данные не повреждены, не потеряны, программа в согласованном состоянии.
Re[3]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 24.06.10 07:12
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

AS>>

To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.


А>Как быть, если в Dispose вызывается Dispose другого класса, который кидает OutOfMemoryException.

А>public class Foo: IDisposable
А>{
А>    private Bar _bar;
А>    void Dispose()
А>    {
А>       if (_bar != null)
А>       {
А>          try
А>          {
А>             _bar.Dispose();
А>          }
А>          catch (OutOfMemoryException)
А>          {
А>          }
А>          _bar = null;
А>       }
А>    }
А>}


Если "другой класс" нельзя сделать по-нормальному, то так как выше сделать можно (дае нужно), но только необходимо в catch написать коментарий о том, какой автор класса Bar нехороший человек и пожелать ему долгих и счастливых лет жизни.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: IDisposable.Dispose() и Exception
От: andy1618 Россия  
Дата: 25.06.10 04:53
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

AS>http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

AS>

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.
Re[3]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 25.06.10 05:23
Оценка:
Здравствуйте, andy1618, Вы писали:

AS>>http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

AS>>

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.
Re[3]: IDisposable.Dispose() и Exception
От: Aen Sidhe Россия Просто блог
Дата: 25.06.10 06:19
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, Aen Sidhe, Вы писали:


AS>>http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

AS>>

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.


Нет, вы не правы.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[4]: IDisposable.Dispose() и Exception
От: anton_t Россия  
Дата: 25.06.10 06:56
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, andy1618, Вы писали:


AS>>>http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

AS>>>

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 не так часто стоит.
Re[4]: IDisposable.Dispose() и Exception
От: cadet354 Россия
Дата: 25.06.10 07:08
Оценка:
Здравствуйте, hardcase, Вы писали:


H>В общем случае — никак, в частном — только если задача решается с помощью CER-блока.

H>АутОфМемори — это грубо говоря полный финиш и лучше рухнуть с перезапуском.
сходу вспоминаю моменты когда работа с System.Drawing при ресайзе картинок например может кинуть это исключение, второе это загрузка большого xml, в обоих случаях можно перехватить как справедливо указал nikov и продолжить работу.
Re[5]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 25.06.10 07:52
Оценка:
Здравствуйте, 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.
Re[6]: IDisposable.Dispose() и Exception
От: anton_t Россия  
Дата: 25.06.10 08:23
Оценка:
Здравствуйте, _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 и подавить исключение, если оно вылетело?
Re[7]: IDisposable.Dispose() и Exception
От: Aen Sidhe Россия Просто блог
Дата: 25.06.10 08:24
Оценка:
Здравствуйте, anton_t, Вы писали:

_>Здравствуйте, _FRED_, Вы писали:


_>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код:

_>
_>File.Delete(tmpFilePath);
_>


_>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?


Если этот код в Dispose — да. Опционально — залогировать.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[8]: IDisposable.Dispose() и Exception
От: anton_t Россия  
Дата: 25.06.10 08:28
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

AS>Здравствуйте, anton_t, Вы писали:


_>>Здравствуйте, _FRED_, Вы писали:


_>>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код:

_>>
_>>File.Delete(tmpFilePath);
_>>


_>>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?


AS>Если этот код в Dispose — да. Опционально — залогировать.


А если логгер в этом Dispose не доступен? Просто проглотить исключение? И потом гадать на кофеной гуще, чего это у клиента темповая дира всё дисковое пространство занимает?
Re[9]: IDisposable.Dispose() и Exception
От: Aen Sidhe Россия Просто блог
Дата: 25.06.10 08:29
Оценка:
Здравствуйте, anton_t, Вы писали:

AS>>Если этот код в Dispose — да. Опционально — залогировать.


_>А если логгер в этом Dispose не доступен? Просто проглотить исключение? И потом гадать на кофеной гуще, чего это у клиента темповая дира всё дисковое пространство занимает?


Если у вас такой замечательный логгер, то да, разумеется, надо наплевать на стандарт и плеваться исключениями налево и направо, раз он недоступен. Кто же запретит то.
С уважением, Анатолий Попов.
ICQ: 995-908
Re[9]: IDisposable.Dispose() и Exception
От: nikov США http://www.linkedin.com/in/nikov
Дата: 25.06.10 08:40
Оценка:
Здравствуйте, 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
        }
    }
}
Re[7]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 25.06.10 11:03
Оценка:
Здравствуйте, anton_t, Вы писали:

_FR>>Не вижу из ваших слов объяснения "почему" Ведь чётко же сказано:

_FR>>

_FR>>…a Dispose method should be callable multiple times without throwing an exception.


_>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код:

_>File.Delete(tmpFilePath);

_>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?


Только так можно избавить от гемороя тех, кто будет такой объект использовать. Иначе же наоборот, теряется весь смысл using-а — вызывающий код обязан оборачивать вызовы Dispose() в try-catch, впрочем, я об этом выше уже сказал.
Help will always be given at Hogwarts to those who ask for it.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.