首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何中断Console.ReadLine

如何中断Console.ReadLine
EN

Stack Overflow用户
提问于 2012-02-28 17:40:40
回答 11查看 21.6K关注 0票数 25

是否可以通过编程方式停止Console.ReadLine()

我有一个控制台应用程序:大部分逻辑在不同的线程上运行,在主线程中,我使用Console.ReadLine()接受输入。当分离的线程停止运行时,我想停止从控制台读取。

我如何才能做到这一点?

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2012-02-28 17:56:36

更新:此技术在Windows10上不再可靠。请不要使用。

在Win10中进行了相当多的实现更改,使控制台的行为更像终端。无疑要协助新的Linux子系统。一个(非故意的?)副作用是CloseHandle()在读操作完成之前会死锁,这会终止这种方法。我会把原来的帖子留在原处,只是因为它可能会帮助别人找到替代方案。

UPDATE2:看一下wischi的答案,找到一个像样的替代方案。

这是可能的,您必须通过关闭stdin流来猛地拉动脚垫。这个程序演示了这个想法:

代码语言:javascript
运行
复制
using System;
using System.Threading;
using System.Runtime.InteropServices;

namespace ConsoleApplication2 {
    class Program {
        static void Main(string[] args) {
            ThreadPool.QueueUserWorkItem((o) => {
                Thread.Sleep(1000);
                IntPtr stdin = GetStdHandle(StdHandle.Stdin);
                CloseHandle(stdin);
            });
            Console.ReadLine();
        }

        // P/Invoke:
        private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetStdHandle(StdHandle std);
        [DllImport("kernel32.dll")]
        private static extern bool CloseHandle(IntPtr hdl);
    }
}
票数 19
EN

Stack Overflow用户

发布于 2012-03-09 21:02:14

将enter发送到当前运行的控制台应用程序:

代码语言:javascript
运行
复制
    class Program
    {
        [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
        private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

        const int VK_RETURN = 0x0D;
        const int WM_KEYDOWN = 0x100;

        static void Main(string[] args)
        {
            Console.Write("Switch focus to another window now.\n");

            ThreadPool.QueueUserWorkItem((o) =>
            {
                Thread.Sleep(4000);

                var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
                PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0);
            });

            Console.ReadLine();

            Console.Write("ReadLine() successfully aborted by background thread.\n");
            Console.Write("[any key to exit]");
            Console.ReadKey();
        }
    }

此代码将enter发送到当前控制台进程,中止在windows内核深层的非托管代码中阻塞的任何ReadLine()调用,这允许C#线程自然退出。

我使用了这段代码,而不是涉及关闭控制台的答案,因为关闭控制台意味着ReadLine()和ReadKey()从此在代码中被永久禁用(如果使用它,它将抛出异常)。

这个答案比涉及SendKeys和Windows Input Simulator的所有解决方案都要好,因为即使当前的应用程序没有重点,它也可以工作。

票数 15
EN

Stack Overflow用户

发布于 2019-10-21 00:58:04

免责声明:这只是一个复制粘贴的答案。

感谢Gérald Barré提供了如此出色的解决方案:

https://www.meziantou.net/cancelling-console-read.htm

CancelIoEX文档:

https://docs.microsoft.com/en-us/windows/win32/fileio/cancelioex-func

我在Windows10上对它进行了测试,它工作得很好,而且比其他解决方案(比如重新实现Console.ReadLine、通过PostMessage发送返回或关闭句柄等)要简单得多。

为了防止网站瘫痪,我在这里引用了代码片段:

代码语言:javascript
运行
复制
class Program
{
    const int STD_INPUT_HANDLE = -10;

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CancelIoEx(IntPtr handle, IntPtr lpOverlapped);

    static void Main(string[] args)
    {
        // Start the timeout
        var read = false;
        Task.Delay(10000).ContinueWith(_ =>
        {
            if (!read)
            {
                // Timeout => cancel the console read
                var handle = GetStdHandle(STD_INPUT_HANDLE);
                CancelIoEx(handle, IntPtr.Zero);
            }
        });

        try
        {
            // Start reading from the console
            Console.WriteLine("Do you want to continue [Y/n] (10 seconds remaining):");
            var key = Console.ReadKey();
            read = true;
            Console.WriteLine("Key read");
        }
        // Handle the exception when the operation is canceled
        catch (InvalidOperationException)
        {
            Console.WriteLine("Operation canceled");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Operation canceled");
        }
    }
}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9479573

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档