6

我的一个班级在应用程序执行期间收集统计信息,我想在应用程序完成时将此统计信息存储到磁盘。我从来没有在我的程序中销毁这个类,所以我试图将日志存储到这样的文件中:

    ~Strategy()
    {
        foreach(var item in statisticItems)
        {
            log.WriteLine(item.Text);    // log is AutoFlush
        }
    }

但是,我没有看到我希望看到的日志,也无法在调用析构函数的调试器时刻“捕捉”。

问题:

  • 为什么在调试器中我无法捕捉到调用析构函数的时刻?程序完成时不是必须为每个对象调用析构函数吗?
  • 我应该用什么来记录我的东西?
4

3 回答 3

1

析构函数(或终结器)不是放置这样的代码的地方。它旨在释放非托管资源。析构函数被称为非确定性的,因此您不能依赖任何在析构函数中有效的对象。而且您无法在调试器中捕获它,因为它是在非常特殊的情况下在单独的线程上调用的。简而言之,不要使用析构函数,除非你知道你需要。

记录应用程序关闭的理想方法是将记录代码简单地放在方法的末尾Main。您应该确保捕获并记录任何抛出的异常,如果是这种情况,您可以在Main.

由于堆栈溢出等错误,将有一些边缘情况您将无法记录关闭。在这些情况下,您将需要依赖错误发生之前发生的事情的日志。

于 2012-07-17T19:38:06.127 回答
-1

不要依赖析构函数。我建议使用这样的东西:

[STAThread]
static void Main()
{
    using(new Strategy())
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

public class Strategy : IDisposable
{
    public void Dispose()
    {
        WriteLogs()
    }
    ...
}

这样您就可以确定您的日志将被写入。

静态 void Main 是从创建 Windows 窗体应用程序时创建的默认 program.cs 复制的。

于 2012-07-17T19:24:03.677 回答
-1

不是一个完整的答案(还),但请查看:

程序员无法控制何时调用析构函数,因为这是由垃圾收集器决定的。垃圾收集器检查应用程序不再使用的对象。如果它认为一个对象符合销毁条件,它会调用析构函数(如果有)并回收用于存储该对象的内存。程序退出时也会调用析构函数。

资料来源:MSDN

如果它是一个控制台应用程序,你能试着打电话Environment.Exit(0);看看会发生什么吗?

让我们保持更新这个答案,因为这是一个有趣的问题。任何人都可以随意编辑。

问候

于 2012-07-17T19:32:48.170 回答