运行一段代码原子或应用程序终止后(Ctrl + C)

时间:2015-10-21 05:54:24

标签: c# terminate kill-process atomicity

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

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

在app kill之后有没有办法将这些队列保存到文件中?或者如何正确地将控制台应用程序作为用户结束。

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

3 个答案:

答案 0 :(得分:2)

Ctrl + C不必杀死应用程序 - 您可以使用Console.CancelKeyPress事件正确处理关闭。至于当用户点击关闭按钮时,你运气不好 - 这实际上是残忍地杀死了这个过程。

您的应用程序应该支持正常关闭。例如,您可以在Console.CancelKeyPress中显示已取消的取消令牌,并且您的代码应该偶尔检查令牌(当您在一个安全的地方时终止)以查看是否请求关闭。

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

答案 1 :(得分:1)

  

有没有办法在app kill后将这些队列保存到文件?

没有。您必须实现退出命令。

Here是解决方案。

答案 2 :(得分:0)

看起来你可以挂钩到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();
    }
}