控制台选择会停止应用

时间:2016-11-02 17:23:50

标签: c# console dllimport

我在我的服务器上运行了一个套接字服务器,我醒来时发现了大量有关其无法访问的消息。事实证明,在我上床睡觉之前,我在窗口中突出显示了一个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时,处理了所有已尝试的连接,然后在处理它们之后,它们被丢弃。这让我想知道,或许,我是否写错了应用程序;我需要一个"控制台"线程和"服务器"线。但我不确定这是否会产生影响。

2 个答案:

答案 0 :(得分:6)

在选择模式下,Windows控制台中的任何线程在写stdoutstderr时都会阻止。与哪个线程无关。

您可以从服务器操作中分离出控制台写入,并确保服务器线程永远不会写入控制台,但是您会引入其他线程管理和消息排队问题。

您可以执行大多数人所做的事情:使用日志文件。如果您不想在应用程序中构建文件写入,只需将stdoutstderr传递给文件,并使用某些等效的tail Windows来监控文件(或像Sublime这样的文本编辑器可以自动监视打开的文件。

server.exe > server.log 2>&1

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

答案 1 :(得分:0)

对于简单的工具,在其他线程中执行控制台写入可能确实是最简单的。 示例代码:

    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();
    }