为什么这个简短的程序永远无法完成?

时间:2018-07-18 06:39:40

标签: c# .net waithandle

通过调试我自己的问题,我设法重新创建了一个行为异常的小程序:

using System;
using System.Threading;

namespace CancelBug
{
    class Program
    {
        static void Main(string[] args)
        {
            var unused = new ManualResetEvent(false);
            var cancelled = new ManualResetEvent(false);
            Console.CancelKeyPress += (s, e) => cancelled.Set();
            Console.WriteLine("Running. The only thing to do now is ctrl+c or close the window...");
            WaitHandle.WaitAny(new[] { unused, cancelled });
            Console.WriteLine("Press enter to continue...");
            Console.Read();
        }
    }
}

我希望该程序能够:

  • 显示第一行
  • 等待,直到用户尝试退出程序
  • 显示第二行
  • 等到用户按下Enter键
  • 退出

但是,一旦这结束了对WaitHandle.WaitAny的调用,它似乎就挂在了随机行上。有时,最后一行将永远不会被打印,有时会被打印,但是回车键永远不会被读取。有了更大的代码库,它可以执行更多的代码行,并且仍然挂在看似随机的位置。

有人能解释这种奇怪的行为吗?

3 个答案:

答案 0 :(得分:8)

您需要取消CTRL+C命令,否则您的进程将终止:

Console.CancelKeyPress += (s, e) =>
{
    e.Cancel = true;
    cancelled.Set();
};

来自https://msdn.microsoft.com/en-us/library/system.consolecanceleventargs(v=vs.110).aspx

  

如果在事件处理程序中将Cancel属性设置为true,则   恢复过程;否则,该过程终止。默认情况下,   ConsoleCancelEventArgs属性的值为false,并且   过程终止。

答案 1 :(得分:0)

Ctrl + C是用于关闭命令窗口的全局命令。因此,此组合键将在实际程序结束之前关闭窗口。尝试使用其他键。

答案 2 :(得分:0)

请在没有调试器的情况下运行应用程序(直接从命令行)。

根据我的测试,这是我的测试应用,其运行情况符合您的预期。

        var cancelled = new ManualResetEvent(false);
        Console.CancelKeyPress += (s, e) =>
        {
            e.Cancel = true;
            Console.WriteLine("Ctrl+C detected...");
            cancelled.Set();
        };
        Console.WriteLine("Running. The only thing to do now is ctrl+c or close the window...");
        WaitHandle.WaitAny(new[] { cancelled });
        Console.WriteLine("Press enter to exit...");
        Console.ReadLine();