Static Finalizer

核能气质少年 提交于 2019-11-28 04:39:34

Basically, you can't. Design your way around it to the fullest extent possible.

Don't forget that a program can always terminate abruptly anyway - someone pulling out the power being the obvious example. So anything you do has to be "best effort" - in which case I'd certainly hope that AppDomain.ProcessExit would be good enough.

What do you need to do, in your particular case?

Herfried Wagner has written an excellent article explaining how to implement this – alas, in German (and VB). Still, the code should be understandable.

I've tried it:

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");
  }
}

It seems to work exactly the same way as the AppDomain.ProcessExit event does: the finalizer gets ca. three seconds...

I would question what you are loading in your static methods that need to be released. I certainly wouldn't recommend doing these things in a static method.

That said, your static method could instanciate an object that has a finalise method.

Two solutions that jump to mind:

  • Don't use a static class. If you use a non-static class and instantiate it, you don't have to worry about cleanup as much.
  • If that's not an option, I'd argue that this is a good situation to use a singleton. This will instantiate a copy of your object and have the finalizer called on exit, but still allow you to treat it like a static class for the most part. After all, your class is static already and therefore shares most of the common reasons not to use a singleton.

To port Michael Damatov's answer (C#) which is based on Herfried K. Wagner. (VB.NET) here is the C++/CLI version:

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. Just like the AppDomain.ProcessExit method, this one may not be called if the process is terminated abnormally (from Task Manager for example). Another word of caution is that if MyClass is generic (templated), the assumption that its static constructor and static destructor will be called no more than once per application execution is no longer be valid.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!