C# 应用程序关闭时将信息存储到文件的正确方法

C# 应用程序关闭时将信息存储到文件的正确方法,c#,C#,我的一个类在应用程序执行期间收集统计信息,我想在应用程序完成时将这些统计信息存储到磁盘。我从未在程序中销毁此类,因此我尝试将日志存储到文件中,如下所示: ~Strategy() { foreach(var item in statisticItems) { log.WriteLine(item.Text); // log is AutoFlush } } 然而,我并没有看到我期望看到的日志,而

我的一个类在应用程序执行期间收集统计信息,我想在应用程序完成时将这些统计信息存储到磁盘。我从未在程序中销毁此类,因此我尝试将日志存储到文件中,如下所示:

    ~Strategy()
    {
        foreach(var item in statisticItems)
        {
            log.WriteLine(item.Text);    // log is AutoFlush
        }
    }
然而,我并没有看到我期望看到的日志,而且当调用析构函数时,我也无法在调试器中“捕捉”到

问题:

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

    • 不要依赖析构函数。我建议您使用以下方法:

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

      这不是一个完整的答案(尚未),但请检查以下内容:

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

      资料来源:

      如果它是一个控制台应用程序,您是否可以尝试调用
      Environment.Exit(0)查看发生了什么

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

      关于

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

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


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

      您是否有可能用停止按钮关闭调试器?@Blindy no I just close the windowIs
      Strategy
      实例化了吗?它是一个静态类(还是只使用它的静态方法)?给我们更多的信息,用例,任何你能做的。您可以针对您的问题忽略框架中的一个bug,它是您代码中的某个bug,我们只能在这一点上猜测。@Blindy是否意味着必须始终调用析构函数,并且建议析构函数是我执行操作的地方?是的
      策略
      是永不满足的,我使用它的实例方法,它是控制台应用程序。@Blindy:不,这不取决于你。在析构函数中引用任何托管对象从来都不是一个好主意。-1用于提升错误的一次性模式。你不应该弄乱这个,使用真正的交易。你为什么要使用属于COM afaik的
      STAThread
      属性?为什么我不应该依赖析构函数?
      一次性的
      是对析构函数的优化(正确的模式包括析构函数),它的主要好处是允许您按需释放资源。@Blindy在我的例子中,我希望避免“按需”。我只想在程序完成后存储所有内容。它回答了“我应该用什么来记录我的东西?”这一问题,现在它也解决了另一个问题。如果你想要一个维基风格的答案,社区维基答案是最好的选择。@KendallFrey如果你不想编辑,你不必这样做。尽管如此,我还是向OP提出了一个问题,我正在等待反馈以改进我的答案。总比只说“你错了,应该这样做”要好。评论是向OP提问的地方。答案是为了答案。@KendallFrey,这很有趣。不是对…的评论吗。。。评论?你在干什么,到处闲逛,抱怨每个人都错了?我想回答这个问题,休息一下。我不是说你错了。我只是想帮你。我对你回答的内容没有异议。我刚才指出了问答系统的工作原理。