控制台选择停止应用程序

7

我在我的服务器上运行了一个socket服务器,当我醒来时,收到了许多关于其无法访问的消息。结果发现,在睡觉前,我在窗口中突出显示了一个IP地址,忘记按Enter键恢复进程。

这是我现在如何禁用控制台中的选择,但我仍希望能够在不暂停应用程序的情况下进行选择。

    #region Disable Quick-Edit Mode
    [DllImport("kernel32.dll")]
    static extern bool SetConsoleMode(IntPtr hConsoleHandle, int mode);

    [DllImport("kernel32.dll")]
    static extern bool GetConsoleMode(IntPtr hConsoleHandle, out int mode);

    [DllImport("kernel32.dll")]
    static extern IntPtr GetStdHandle(int handle);

    const int STD_INPUT_HANDLE = -10;
    const int ENABLE_EXTENDED_FLAGS = 0x80;

    public static void DisableQuickEditMode()
    {
        int mode;
        IntPtr handle = GetStdHandle(STD_INPUT_HANDLE);
        GetConsoleMode(handle, out mode);
        mode |= ENABLE_EXTENDED_FLAGS;
        SetConsoleMode(handle, mode);
        mode &= ~ENABLE_QUICK_EDIT;
        SetConsoleMode(handle, mode);
    }

我真的不想回到命令提示符的传统模式,因为这些新功能确实有助于开发人员,但我需要找到一种方法,在暂停控制台时防止应用程序停止。

有趣的是,今天早上当我按下Enter键时,所有已尝试的连接都被处理了,然后在处理完它们后,它们被关闭了。这让我想知道,也许我写的应用程序有问题;我需要一个“Console”线程和一个“Server”线程。但我不确定这会有什么区别。


2
这种情况发生在运行在Windows上的每个控制台程序中,这只是由于您的选择阻止新输出被显示的结果,进而最终阻止像Console.WriteLine()这样的调用完成,因为输出缓冲区已满。这个问题与编程无关,它是一个基本的Windows用户主题。 - Peter Duniho
哦,对不起。我从来没有意识到那是这种情况;我很少使用控制台应用程序,我只是假设大多数程序员都有一个解决方法。请原谅。 - Fuselight
2个回答

8
当处于选择模式时,Windows控制台中的任何线程在写入stdoutstderr时都会被阻塞。无论是哪个线程。
您可以将控制台写入与服务器操作分离,并确保服务器线程永远不会写入控制台,但这样会引入额外的线程管理和消息队列问题。
您可以像大多数人一样使用日志文件。如果您不想将文件写入应用程序中,则只需将stdoutstderr管道到文件中,并使用某个Windows等效的tail来监视该文件(或类似Sublime这样自动监视打开文件的文本编辑器)。
server.exe > server.log 2>&1

澄清一下:2>&1 表示应该将 stderr(文件句柄2)与 stdout(文件句柄1)"合并"。


嗯,值得思考的食物。谢谢! - Fuselight

1

对于简单的工具,执行控制台写入不同的线程可能是最容易的。 示例代码:

    static BlockingCollection<string> messageQueue = new BlockingCollection<string>(new ConcurrentQueue<string>());
    static Task messagePrinterTask;
    private static void ConsoleWriteLine(string s)
    {
        messageQueue.Add(s);
    }
    private static void StartMessageQueuePrinter()
    {
        messagePrinterTask = Task.Run(() =>
        {
            try { while(true) Console.WriteLine(messageQueue.Take()); }
            catch (InvalidOperationException) { } //CompleteAdding called.
        });
    }
    private static void StopMessageQueuePrinter()
    {
        messageQueue.CompleteAdding();
        messagePrinterTask.Wait();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接