Использование располагает на Singleton к ресурсам очистки

Вопрос, который я имею, мог бы больше относиться к семантике, чем с фактическим использованием IDisposable. Я работаю над реализацией singleton-класса, который отвечает за управление экземпляром базы данных, который создается во время выполнения приложения. Когда приложение закрывается, эта база данных должна быть удалена.

Прямо сейчас я имею, это удаляет быть обработанным a Cleanup() метод одиночного элемента, который называет приложение, когда это закрывается. Поскольку я писал документацию для Cleanup() это ударило меня, что я описывал что a Dispose() метод должен использоваться для т.е. моющиеся ресурсы. Я первоначально не реализовал IDisposable потому что это казалось неуместным в моем одиночном элементе, потому что я не хотел, чтобы что-либо расположило сам одиночный элемент. В настоящее время нет, но в будущем могла бы быть причина что это Cleanup() мог бы быть назван, но одиночный элемент должен должным быть все еще существовать. Я думаю, что могу включать GC.SuppressFinalize(this); в Расположить методе для создания этого выполнимым.

Мой вопрос поэтому мультиразделен:

1) Реализует IDisposable на одиночном элементе существенно плохая идея?

2) Я просто смешиваю семантику здесь при наличии a Cleanup() вместо a Dispose() и так как я располагаю ресурсы, я действительно должен использовать расположение?

3) Будет реализация 'Располагать ()' с GC.SuppressFinalize(this); сделайте его так, мой одиночный элемент на самом деле не уничтожается в случае, я хочу, чтобы это жило после вызова к очистке база данных.

7
задан Craig Suchanec 28 May 2010 в 17:48
поделиться

3 ответа

Короче говоря, если у вас есть синглтон и вы вызываете dispose. Любой объект, который попытается использовать его после этого, будет использовать объект в состоянии dispose.

Теперь размещение и утилизация объекта после того, как приложение закончит работу с ним, не обязательно плохо. Однако нужно быть осторожным при его вызове. Если вы действительно обеспокоены очисткой и у вас только одна ссылка на объект, вы можете поместить код очистки в финализатор объектов ~YourClass, и тогда он будет вызываться только тогда, когда .Net убедится, что он больше не нужен (при закрытии приложения, если это настоящий синглтон).

Не смешиваю ли я семантику здесь, имея имея Cleanup() вместо Dispose(), и поскольку я утилизирую ресурсов, я действительно должен использовать dispose?

Да, это просто семантика. Dispose - это стандарт для того, чтобы показать, что есть вещи, которые должны быть очищены после того, как программа закончит работу с объектом.

Будет ли реализация 'Dispose()' с помощью GC.SuppressFinalize(this); сделает так, что мой синглтон не будет фактически уничтожен в случае, если я хочу, чтобы он оставался живым после вызова для очистки базы данных.

Нет, это означает, что когда вы вызываете метод dispose, сборщик мусора не будет вызывать пользовательский финализатор объекта.

8
ответ дан 6 December 2019 в 12:46
поделиться
  1. Реализация IDisposable для синглтона может быть хорошей идеей, если вы используете технологию CAS вместо блокировок для создания синглтона. Что-то вроде этого.

     if (instance == null) {
    var temp = new Singleton ();
    if (Interlocked.CompareExchange (ref instance, temp, null)! = null) &&
    temp IDisposable) {
     ((IDisposable) temp).Dispose ();
     }
    }
    возвратный экземпляр
    

    Мы создали временный объект и попробовали атомарное сравнение и обмен, поэтому нам нужно удалить этот временный объект, если он реализует IDisposable и он не был записан в местоположение экземпляра.

    Было бы неплохо избежать блокировок, но также это немного накладные расходы, если для создания экземпляра синглтона в его конструкторе используется сложная логика.

  2. Если вы не хотите, чтобы другой код очищал или удалял ваш объект, просто не предоставляйте для этого никакой возможности. Однако может быть хорошей идеей предоставить какой-то метод reset (), позволяющий синглтону воссоздать себя, если, скажем, вы используете ленивую инициализацию. Примерно так:

     public static Singletong GetInstance () {
    if (instance == null) {
    экземпляр = новый синглтон (); // здесь мы, например, повторно вычисляем кеш
     }
    возвратный экземпляр
    }
    public static void Reset () {
    instance = null;
    }
    
7
ответ дан 6 December 2019 в 12:46
поделиться

Я согласен с ответом Кевина, но хотел бы кое-что добавить к этому. Меня немного смущает ваше утверждение:

Когда приложение закрывает это базу данных следует удалить.

Вы действительно имеете в виду удаленные? Как в уничтоженном? Вы говорите о реальной (SQL) базе данных?

Вы должны понимать, что даже если вы поместите свой код очистки в финализатор или в событие Application_End (ASP.NET), вы не можете гарантировать, что они будут вызваны . Процесс может быть прерван, или компьютер потеряет питание. Кажется более разумным удалить базу данных при запуске приложения или, по крайней мере, иметь резервный механизм при запуске с некоторой очисткой.

Хотя финализатор был бы хорошим местом для очистки при работе с ресурсами, в вашем случае мы говорим о ресурсе приложения . Я имею в виду, что ресурс, возможно, не привязан к одному объекту (вашему синглтону), но является частью всего приложения. Это может стать немного абстрактным обсуждением, и, возможно, это скорее вопрос взгляда.

Я пытаюсь сказать, что когда вы видите эту базу данных как ресурс приложения, вам нужно будет, чтобы ваша инициализация и очистка были привязаны не к объекту, а к приложению. В приложении ASP.NET это будет Application_Start и Application_End (global.asax). В приложении Windows Forms это будет Program.Main.

Тем не менее, при использовании этих механизмов вместо финализаторов у вас нет уверенности в том, что ваш код очистки выполнится.

1
ответ дан 6 December 2019 в 12:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: