1

How to interrupt Console.ReadLine to figure out to interrupt a Console.ReadlLine(and Console.ReadKey) 之后,我遇到了以下行为(我不知道这是否是 Windows、.NET 框架或诸如此类的错误):当我使用CancelIoEx取消 a ReadKey(或ReadLine),它成功地取消了读取(即中断调用并且线程继续),但似乎读取操作仍在控制台中发生(完成后将被忽略)。

难道我做错了什么?它是 Windows/.NET 中的错误吗?我应该执行其他操作来停止实际读取吗?

如何重现:

  1. 我正在使用带有 .NET Framework 4.7.2 的控制台项目(这也将在 .NET5.0 上重现)。
  2. 我正在运行以下代码:
    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. 等待 2 秒,然后单击一个键(该键被忽略),然后单击另一个键(将被写入)。'a' 然后 'b' 的输出:
Read key1
Interrupting...
Read key2
Keys: , B
  1. 我希望第一次实际读取 (for key2) 不会被忽略(即,输出会说Keys: , A,我将没有机会单击“b”)。
  2. 请注意,如果我在控制台中更改某些内容(更改其大小或最小化/最大化),它将按预期运行:2 秒后,它会中断,我更改大小,单击a并完成。无需额外的按键输入。

请注意,在尝试使用它时,我也遇到了以下行为:

  1. 更改为try_ReadHiddenKey
                var str = Console.ReadLine();
                result = ConsoleKey.Enter;
                Console.WriteLine("Read: " + str);
  1. Console.ReadKey();在第二个之前添加ReadHiddenKey

写入abcthen enter 然后再1234enter 的结果是:

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

证明行为是第一个Console.ReadLine()抛出异常,但照常继续(因此我写的第一行是“吞下”)。

4

0 回答 0