2008-11-01 5 views
36

Каков правильный способ выполнения некоторой статической финализации?Статический финализатор

Нет статического деструктора. Событие AppDomain.DomainUnload не отображается в домене по умолчанию. Событие AppDomain.ProcessExit разделяет общее время в три секунды (настройки по умолчанию) между всеми обработчиками событий, поэтому оно не может использоваться.

+2

Во-первых, на C# нам нужно отказаться от привычного использования финализатора и деструктора. Один из них детерминирован, другой - нет. Интересно отметить, что спецификация C# возвращает термины обратно из CLR и других спецификаций языка .NET.Интересно также отметить, что в примечаниях к языковому комитету C# явно говорится, что нет никаких причин, по которым C# не может иметь статические финализаторы. http://stackoverflow.com/a/1875149/56793 – JMD 2014-09-26 14:10:01

ответ

27

В принципе, вы не можете. Создайте свой путь вокруг него в максимально возможной степени.

Не забывайте, что программа может всегда прекратить круто в любом случае - кто-то вытащил силу, являющуюся очевидным примером. Итак, все, что вы делаете, должно быть «наилучшим усилием» - и в этом случае я, конечно, буду надеюсь, что, что AppDomain.ProcessExit будет достаточно хорошим.

Что вам нужно делать в вашем конкретном случае?

+1

Как этот ответ относится к ответу Майкла (так как, возможно, есть статические финализаторы)? (В любом случае я согласен с тем, что финализаторы ненадежны.) – mafu 2012-02-29 16:02:38

+0

@mafutrct: Ответ Майкла на самом деле не является статическим финализатором. Это статическое поле со ссылкой на экземпляр с финализатором. Это не одно и то же, хотя это может иметь похожие последствия. Я бы не использовал его лично. – 2012-02-29 16:04:41

6

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

Таким образом, ваш статический метод может создать объект, который имеет метод finalize.

6

Два решения, которые прыгают на ум:

  • Не используйте статический класс. Если вы используете нестатический класс и создаете его, вам не нужно беспокоиться об очистке.
  • Если это не вариант, я бы сказал, что это хорошая ситуация для использования синглтона. Это создаст экземпляр копии вашего объекта и вызовет финализатор при выходе, но по-прежнему позволит вам рассматривать его как статический класс по большей части. В конце концов, ваш класс уже статичен и поэтому разделяет большинство распространенных причин не использовать синглтон.
39

Herfried Вагнер написал excellent article объясняющую, как осуществить это - увы, на немецком языке (и VB). Тем не менее, код должен быть понятным.

Я пробовал:

static readonly Finalizer finalizer = new Finalizer(); 

sealed class Finalizer { 
    ~Finalizer() { 
    Thread.Sleep(1000); 
    Console.WriteLine("one"); 
    Thread.Sleep(1000); 
    Console.WriteLine("two"); 
    Thread.Sleep(1000); 
    Console.WriteLine("three"); 
    Thread.Sleep(1000); 
    Console.WriteLine("four"); 
    Thread.Sleep(1000); 
    Console.WriteLine("five"); 
    } 
} 

Это, кажется, работает точно так же, как AppDomain.ProcessExit событие делает: финализации получает ca. три секунды ...

0

Чтобы отправить ответ Майкла Даматова (C#), который основан на Херфриде К. Вагнере. (VB.NET) здесь - версия C++/CLI:

ref class MyClass 
{ 
     ref class StaticFinalizer sealed 
     { 
      !StaticFinalizer(); 
     }; 
     static initonly StaticFinalizer^ stDestr = gcnew StaticFinalizer(); 
} 

MyClass::StaticFinalizer::!StaticFinalizer() 
{ 
    System::Diagnostics::Debug::WriteLine("In StaticFinalizer!"); 
} 

P.S. Подобно методу AppDomain.ProcessExit, этот вызов нельзя вызывать, если процесс прерывается ненормально (например, из диспетчера задач). Еще одно предостережение заключается в том, что если MyClass является общим (шаблонным), предположение о том, что его статический конструктор и статический деструктор будет вызываться не более одного раза на выполнение приложения, больше недействительно.