Why does this short program never complete?

107 views Asked by At

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?

3

There are 3 answers

2
Freggar On BEST ANSWER

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.

0
Venu prasad H S On

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.

1
tmaj On

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