我有一个用C#编写的应用程序,它通过while(true)循环和Console.ReadLine连续获取用户的命令。
我也有各种后台操作,可通过控制台报告。查看这个简单的例子:
class Program
{
static void Main(string[] args)
{
new Messager(1000 * 2.5f);
new Messager(1000 * 3);
while (true)
{
Console.ReadLine();
}
}
}
public class Messager
{
Timer Timer;
public Messager(double interval)
{
this.Timer = new Timer(interval);
this.Timer.Elapsed += (sender, e) =>
{
Console.WriteLine("message from " + this.Timer.Interval);
};
this.Timer.Start();
}
}
问题是,当我输入命令并且在按下Enter之前Messager报告回来时,来自Messager的消息将被附加到我当前的行,光标将被放入下一行。见这个截图:
正如你猜我不想那样。我希望当前输入的命令始终保持在最后一行,并将所有消息放在该行之上。正如您对此类应用程序的期望一样。我如何实现这一目标?
答案 0 :(得分:5)
这非常非常困难。您最终编写自己的控制台输入和输出方法,每个线程都必须调用。如果任何线程不合作,它就行不通。但是可以使用Console API。
基本思想是让您的公共输出函数写入控制台屏幕缓冲区,并在代码中滚动缓冲区,而不是让文本流到最后一行并自动滚动。我记得,你必须解析换行符和其他控制字符的输出,并正确处理它们。
您可以在最后一行使用Console.ReadLine
,但如果用户输入的文字多于单行上的文字,则可能会出现问题。此外,用户在该行的末尾点击Enter可能会导致它向上滚动。在这种情况下使用原始控制台输入可能是最好的。
您希望对Windows consoles非常熟悉。
预先警告:这是很多工作。并且可能不值得努力。
答案 1 :(得分:3)
以下是我的问题的答案:
class Program
{
static void Main(string[] args)
{
new Messager(1000 * 2.5f);
new Messager(1000 * 3);
while (true)
{
Console.ReadLine();
}
}
}
public class Messager
{
Timer Timer;
public Messager(double interval)
{
this.Timer = new Timer(interval);
this.Timer.Elapsed += (sender, e) =>
{
int currentTopCursor = Console.CursorTop;
int currentLeftCursor = Console.CursorLeft;
Console.MoveBufferArea(0, currentTopCursor, Console.WindowWidth, 1, 0, currentTopCursor + 1);
Console.CursorTop = currentTopCursor;
Console.CursorLeft = 0;
Console.WriteLine("message from " + this.Timer.Interval);
Console.CursorTop = currentTopCursor +1;
Console.CursorLeft = currentLeftCursor;
};
this.Timer.Start();
}
}
答案 2 :(得分:0)
只是一个想法。您可以使用Console.CursorTop
和Console.CursorLeft
属性。
class Program
{
static void Main(string[] args)
{
new Messager(1000 * 2.5f);
new Messager(1000 * 3);
while (true)
{
Console.CursorTop = 0;
Console.ReadLine();
}
}
}
public class Messager
{
Timer Timer;
static int position = 1;
public Messager(double interval)
{
this.Timer = new Timer(interval);
this.Timer.Elapsed += (sender, e) =>
{
lock (this)
{
var cursorLeft = Console.CursorLeft;
Console.CursorLeft = 0;
Console.CursorTop = position++;
Console.WriteLine("message from " + this.Timer.Interval);
Console.CursorTop = 0;
Console.CursorLeft = cursorLeft;
}
};
this.Timer.Start();
}
}