【问题标题】:Run piece of code atomic or after application kill (Ctrl+C) [duplicate]运行一段代码原子或在应用程序终止后(Ctrl+C)[重复]
【发布时间】:2015-10-21 14:23:03
【问题描述】:

在我的程序中,我会在每次循环迭代中处理文本文件,以免在运行过程中丢失任何数据。这是残酷的无效,我昨天仍然丢失了那些数据。

我有 2 个队列 - “我做了什么”和“该做什么”。一段时间后,我需要结束此应用程序并记住这些队列以供下一次应用程序运行。我通常用 Ctrl+C 杀死应用程序。

有没有办法在应用程序终止后将这些队列保存到文件中?或者如何正确以用户身份结束控制台应用程序。

是否可以原子地运行一段代码? 我的意思是当我通过删除它的第一行来更新一些“队列文件”时,我需要将整个文件复制到 tmp 而不是删除原始文件,而不是将 tmp 文件复制到原始文件。但有时我在 orig 之后立即按 Ctrl+C。文件删除,我丢失了一个队列。

【问题讨论】:

  • 首先:不要杀死您的程序 - 使用某种用户交互(一个简单的基于文本的菜单即可)并以保存方式退出它 - 然后你为什么不先将这一行添加到 done 并从 todo 中删除它 - 你不必复制文件,即使你之间失败了查看匹配的条目并知道您必须删除 todo 部分...当然,另一种选择是将您的条目标记为 done ...
  • @Carsten 我的程序根本不与用户交互,它只是在爬网。似乎这个答案解决了我的问题:stackoverflow.com/a/22996661

标签: c# terminate kill-process atomic


【解决方案1】:

Ctrl+C 不一定会终止应用程序 - 您可以使用 Console.CancelKeyPress 事件正确处理关闭。至于当用户点击关闭按钮时,你就不走运了——这实际上会残忍地杀死进程。

您的应用程序应该支持正常关闭。例如,您可能有一个在Console.CancelKeyPress 中发出信号的取消令牌,并且您的代码应不时检查该令牌(当您处于可以安全终止的位置时)以查看是否请求关闭。

作为一项额外措施,您可以尝试使用一些更安全的操作措施。例如,您可以重命名它,而不是删除原始文件。如果你的处理中途失败了,文件还在,你可以在应用程序重新启动时恢复它。只有当一个新文件被完全处理和复制后,你才会删除原来的文件。

【讨论】:

    【解决方案2】:

    有什么方法可以在应用终止后将这些队列保存到文件中?

    没有。您必须执行退出命令。

    Here 是解决方案。

    【讨论】:

      【解决方案3】:

      看起来您可以挂接到 CTRL-C 或 CTRL-BREAK 信号以优雅地退出您的应用程序。

      class Program
      {
          //https://msdn.microsoft.com/en-us/library/windows/desktop/ms683231(v=vs.85).aspx
          private const int STD_INPUT_HANDLE = -10;
          private const uint ENABLE_PROCESSED_INPUT = 0x0001;
      
      
          [DllImport("Kernel32.dll")]
          private static extern IntPtr GetStdHandle(int nStdHandle);
      
          [DllImport("Kernel32.dll")]
          private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
      
          [DllImport("Kernel32.dll")]
          private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint dwMode);
      
          static void Main(string[] args)
          {
              IntPtr handle = GetStdHandle(STD_INPUT_HANDLE);
      
              uint mode;
              GetConsoleMode(handle, out mode);
              mode &= ~ENABLE_PROCESSED_INPUT;
      
              SetConsoleMode(handle, mode);
      
              new Thread(() =>
              {
                  while (true)
                  {
                      var chara = Console.ReadKey();
      
                      if (chara.KeyChar == 3)
                      {
                          Console.WriteLine("ctrl-c");
                          //signal to gracefully exit
                      }
      
                      Console.WriteLine("c:{0}", chara);
                  }
      
              }).Start();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-08-21
        • 2013-05-12
        • 2018-03-31
        • 2020-02-03
        • 1970-01-01
        • 1970-01-01
        • 2021-11-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多