简体   繁体   中英

Why does this short program never complete?

Through debugging a problem of my own, I have managed to recreate a tiny program which behaves very unusually:

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();
        }
    }
}

I would expect this program to:

  • display the first line
  • wait until the user tries to exit the program
  • display the second line
  • wait until the user presses enter
  • exit

However, once this makes it past the call to WaitHandle.WaitAny , it seems to hang on random lines. Sometimes the last line will never be printed, sometimes it will be printed but the enter key is never read. With a larger code base, it can execute more lines of code and still hang at a seemingly random position.

Can anyone explain this strange behaviour?

You need to cancel the CTRL+C command or else your process will be terminated:

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

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

If the Cancel property is set to true in the event handler, the process is resumed; otherwise, the process is terminated. By default, the value of the ConsoleCancelEventArgs property is false, and the process terminates.

Ctrl + C is global command to close the command window. So, This key combination will close the window before the actual program ends. Try using other key.

Please run the application without the debugger (directly from the command line).

Here's my test app that behaves as you expect, according to my test.

        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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM