c# - 控制台应用程序 - 当前工作线上方的 WriteLine

标签 c# console-application

我看过其他一些与此非常相似的帖子,但他们给出的答案并没有正确回答问题。抱歉,如果有什么隐藏的东西我找不到...

我想使用 Console.WriteLine() 在我当前的 Console.ReadLine() 之上打印一些内容,例如,我的应用程序打印“Hello world”并启动一个线程(在 5 秒内)将打印“I just waited在我需要输入内容的行上方 5 秒”,如下所示:

Hello world
Please input something: _

然后 5 秒会过去,它看起来像这样:

Hello world
I just waited 5 seconds
Please input something: _

到目前为止,我已经尝试使用 Console.SetCursorPosition(0,Console.CursorTop - 1) 但这只会打印“请输入内容:_”这一行,如果我使用 Console.CursorTop - 2,它会崩溃并显示“[2] 超出范围”(不知道这是为什么),如果我使用 Console.CursorTop - 2,它会在“请输入内容:_”下打印...所以我的问题是如何在“请”行上方打印内容输入一些东西:_”

最佳答案

仅仅移动光标是不够的,问题是你正在插入文本。这是可能的,Console.MoveBufferArea() 方法使您可以访问控制台的底层屏幕缓冲区,并允许您将文本和属性移动到另一行。

有几个棘手的极端情况。您已经找到了一个,如果光标位于缓冲区的末尾,则必须强制控制台滚动。计时器是一个非常难解决的问题,只有在计时器的 Elapsed 事件插入文本的同时阻止 Console.ReadLine() 移动光标,您才能真正正确地做到这一点。这需要一个,您不能在 Console.ReadLine() 中插入锁。

您可以使用一些示例代码来实现目标:

static string TimedReadline(string prompt, int seconds) {
    int y = Console.CursorTop;
    // Force a scroll if we're at the end of the buffer
    if (y == Console.BufferHeight - 1) {
        Console.WriteLine();
        Console.SetCursorPosition(0, --y);
    }
    // Setup the timer
    using (var tmr = new System.Timers.Timer(1000 * seconds)) {
        tmr.AutoReset = false;
        tmr.Elapsed += (s, e) => {
            if (Console.CursorTop != y) return;
            int x = Cursor.Left;
            Console.MoveBufferArea(0, y, Console.WindowWidth, 1, 0, y + 1);
            Console.SetCursorPosition(0, y);
            Console.Write("I just waited {0} seconds", seconds);
            Console.SetCursorPosition(x, y + 1);
        };
        tmr.Enabled = true;
        // Write the prompt and obtain the user's input
        Console.Write(prompt);
        return Console.ReadLine();
    }
}

示例用法:

static void Main(string[] args) {
    for (int ix = 0; ix < Console.BufferHeight; ++ix) Console.WriteLine("Hello world");
    var input = TimedReadline("Please input something: ", 2);
}

注意 Console.Top 属性上的测试,它确保当用户键入过多文本并强制滚动时,或者如果 Console.ReadLine() 在计时器计时的同一时间完成,不会出现严重错误。很难证明它在所有可能的情况下都是线程安全的,当 Console.ReadLine() 在 Elapsed 事件处理程序运行的同一时间水平移动光标时肯定会出现问题。我建议你写 your own Console.ReadLine() method这样您就可以插入锁并确信它始终是安全的。

关于c# - 控制台应用程序 - 当前工作线上方的 WriteLine,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42111078/

相关文章:

c++ - 控件在 snake 中没有正确响应

C# MVC-发布一个包含字典的 View 模型

c# - Silverlight/C# 图像未找到异常处理

c# - 类嵌套和访问修饰符

c# - 如何永久禁用特定字段的 mvc 客户端验证?

c# - 回调函数

c# - 'LibGit2Sharp.Core.NativeMethods' 的类型初始值设定项抛出异常

c# - 控制台应用程序中的 Instasharp

c# - 在主机服务器上运行控制台应用程序

c# - 如何在 C# 的控制台应用程序中设置鼠标光标的位置?