1

Following How to interrupt Console.ReadLine to figure out to interrupt a Console.ReadlLine (and Console.ReadKey), I encountered the following behavior (I don't know if it's a bug in Windows, the .NET framework, or whatnot): When I use CancelIoEx to cancel a ReadKey (or ReadLine), it cancels the read successfully (i.e., interrupts the call and the thread continues), but it seems the read action is still happening in the console (and will be ignored when done).

Am I doing something wrong? Is it a bug in Windows/.NET? Should I perform another action to stop the actual read?

How to reproduce:

  1. I'm using a console project with .NET Framework 4.7.2 (this would reproduce on .NET5.0 as well).
  2. I'm running the following code:
    class Program
    {
        const int STD_INPUT_HANDLE = -10;
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetStdHandle(int nStdHandle);
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool CancelIoEx(IntPtr handle, IntPtr lpOverlapped);

        private static void InterruptReadLine()
        {
            var handle = GetStdHandle(STD_INPUT_HANDLE);
            bool success = CancelIoEx(handle, IntPtr.Zero);
        }

        private static ConsoleKey? ReadHiddenKey()
        {
            ConsoleKey? result = null;
            try
            {
                result = Console.ReadKey(true).Key;
            }
            // This is interrupted on Dispose.
            catch (InvalidOperationException) { }
            catch (OperationCanceledException) { }
            return result;
        }

        static void Main(string[] args)
        {
            Task task = Task.Delay(2000).ContinueWith(_ =>
            {
                Console.WriteLine("Interrupting...");
                InterruptReadLine();
            });

            Console.WriteLine("Read key1");
            var key1 = ReadHiddenKey();
            Console.WriteLine("Read key2");
            var key2 = ReadHiddenKey();
            Console.WriteLine($"Keys: {key1}, {key2}");
        }
    }
  1. Wait 2 seconds, then click a key (the key is ignored) and then another key (which will be written). The output for 'a' then 'b':
Read key1
Interrupting...
Read key2
Keys: , B
  1. I would expect the first actual read (for key2) would not be ignored (i.e., the output would say Keys: , A and I will not have a chance to click 'b').
  2. Note that if I change something in the console (change its size, or minimize/maximize) it then behaves as expected: After 2 seconds, it interrupts, I change the size, click a and its done. No need for an extra key input.

Note that when experimenting with it I encountered the following behavior as well:

  1. Changing the try in ReadHiddenKey to
                var str = Console.ReadLine();
                result = ConsoleKey.Enter;
                Console.WriteLine("Read: " + str);
  1. Adding Console.ReadKey(); before the second ReadHiddenKey.

The result for when writing abc then enter and then 1234 and enter is:

Read key1
Interrupting...
Read key2
abc
1234
Read: 234
Keys: , Enter

Proving that the behavior is that the first Console.ReadLine() throws an exception, but continues as usual (thus the first line I write is "swallowed").

Your_Eye
  • 31
  • 4
  • based on my test, I almost reproduced your problem. I can get the value even if I cancel the readkey. I think it is the problem that CancelIoEx only canceled the process to run the console.readkey method, but it doesn't cancel the process that get the value from console. If you want to do more research, I recommend that you can ask for help in [Developer Community](https://developercommunity.visualstudio.com/spaces/8/index.html) for .net question. – Jack J Jun Jan 25 '21 at 08:42
  • Thanks! Done. https://developercommunity2.visualstudio.com/t/cancelling-read-key-with-cancelioex-also-interrupt/1324943?from=email – Your_Eye Jan 29 '21 at 15:43
  • Also posted on https://learn.microsoft.com/en-us/answers/questions/254413/cancelling-read-key-with-cancelioex-also-interrupt.html. – Your_Eye Feb 01 '21 at 20:19

0 Answers0