【问题标题】:correct way to store information to file when application shutdown应用程序关闭时将信息存储到文件的正确方法
【发布时间】:2012-07-16 18:32:17
【问题描述】:

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

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

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

问题:

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

【问题讨论】:

  • 您是否会使用停止按钮关闭调试器?
  • @Blindy 不,我只是关闭窗口
  • Strategy 是否已实例化?它是一个静态类(或者你只使用它的静态方法)?给我们更多信息,用例,你可以的任何东西。您可以针对您的问题忽略框架中的错误,它是您的代码中的某些内容,我们只能在这一点上猜测。
  • @Blindy 这是否意味着必须始终调用析构函数并且建议使用析构函数来做我做的事情?是的Strategy 很满足,我用它的实例方法,它的控制台应用程序。
  • @Blindy:不,这不取决于你。在析构函数中引用任何托管对象绝不是一个好主意。

标签: c#


【解决方案1】:

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

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

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

【讨论】:

  • 它回答了“我应该用什么来记录我的东西?”的问题
  • 它现在也解决了另一个问题。
【解决方案2】:

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

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

来源:MSDN

如果它是一个控制台应用程序,您可以尝试拨打Environment.Exit(0); 看看会发生什么吗?

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

问候

【讨论】:

  • 如果您想要一个 wiki 风格的答案,社区 wiki 答案是最好的选择。
  • @KendallFrey 如果您不想编辑,则不必这样做。尽管如此,我还是向 OP 提出了一个问题,我正在等待反馈以改进我的答案。比仅仅说“你错了,应该这样做”更好
  • cmets 是向 OP 提问的地方。答案是为了答案。
  • @KendallFrey 这很有趣。 cmets 不是用于... cmets 吗?你在做什么,四处浏览并抱怨每个人都错了?我正在尝试回答这个问题,休息一下。
  • 我不是说你错了。我只是想帮你。我对你回答的内容没有任何异议。我只是指出了问题/评论/答案系统的工作原理。
【解决方案3】:

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

[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 复制的。

【讨论】:

  • -1 用于推广错误的一次性模式。你不应该弄乱这个,使用真正的交易。
  • 你为什么使用属于 COM afaik 的STAThread 属性?为什么我不应该依赖析构函数?
  • Disposable 是对析构函数的优化(并且正确的模式无论如何都包括析构函数),它的主要好处是它允许您按需释放资源。
  • @Blindy 就我而言,我想避免“按需”。我只想在程序完成后存储所有内容。
猜你喜欢
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
  • 2019-05-09
  • 2012-03-08
  • 1970-01-01
  • 2013-08-05
  • 1970-01-01
  • 2017-10-23
相关资源
最近更新 更多