Статический финализатор - PullRequest
40 голосов
/ 01 ноября 2008

Как правильно выполнить статическую финализацию?

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

Ответы [ 5 ]

44 голосов
/ 02 ноября 2008

Херфрид Вагнер написал превосходную статью , объясняющую, как это реализовать - увы, на немецком языке (и 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: финализатор получает ок. три секунды ...

30 голосов
/ 01 ноября 2008

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

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

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

6 голосов
/ 01 ноября 2008

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

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

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

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

0 голосов
/ 01 августа 2014

Портировать ответ Михаила Даматова (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 является универсальным (шаблонным), предположение о том, что его статический конструктор и статический деструктор будут вызываться не более одного раза за выполнение приложения, больше не будет верным.

...