45

执行某些静态终结的正确方法是什么?

没有静态析构函数。该AppDomain.DomainUnload事件不会在默认域中引发。该AppDomain.ProcessExit事件在所有事件处理程序之间共享三秒(默认设置)的总时间,因此它不是真正可用的。

4

5 回答 5

49

Herfried Wagner 写了一篇很好的文章,解释了如何实现这一点——唉,用德语(和 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. 三秒……

于 2008-11-01T23:51:57.930 回答
32

基本上,你不能。尽最大可能设计自己的方式。

不要忘记程序总是可以突然终止——有人拔掉电源就是一个明显的例子。所以你所做的任何事情都必须是“尽力而为”——在这种情况下,我当然希望AppDomain.ProcessExit已经足够好了。

在您的特定情况下,您需要做什么?

于 2008-11-01T20:40:44.807 回答
8

两个让我想到的解决方案:

  • 不要使用静态类。如果您使用非静态类并将其实例化,则不必担心清理工作。
  • 如果这不是一个选项,我认为这是使用单例的好情况。这将实例化您的对象的副本并在退出时调用终结器,但仍然允许您在大多数情况下将其视为静态类。毕竟,您的类已经是静态的,因此共享不使用单例的大多数常见原因。
于 2008-11-01T20:59:25.393 回答
6

我会质疑您在需要释放的静态方法中加载的内容。我当然不建议用静态方法做这些事情。

也就是说,您的静态方法可以实例化具有 finalize 方法的对象。

于 2008-11-01T20:40:51.407 回答
1

移植基于 Herfried K. Wagner 的 Michael Damatov 的答案 (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!");
}

PS 就像 AppDomain.ProcessExit 方法一样,如果进程异常终止(例如从任务管理器中),则可能不会调用此方法。另一个要注意的是,如果 MyClass 是泛型的(模板化的),那么每次应用程序执行不超过一次调用其静态构造函数和静态析构函数的假设不再有效。

于 2014-07-31T20:03:23.863 回答