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:
- I'm using a console project with .NET Framework 4.7.2 (this would reproduce on .NET5.0 as well).
- 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}");
}
}
- 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
- I would expect the first actual read (for
key2
) would not be ignored (i.e., the output would sayKeys: , A
and I will not have a chance to click 'b'). - 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:
- Changing the
try
inReadHiddenKey
to
var str = Console.ReadLine();
result = ConsoleKey.Enter;
Console.WriteLine("Read: " + str);
- Adding
Console.ReadKey();
before the secondReadHiddenKey
.
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").